Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
M1888
lottokone
Commits
1ad184e4
Commit
1ad184e4
authored
Apr 16, 2019
by
M1888
Browse files
iltakoodailut
parent
a0d0345c
Changes
8
Hide whitespace changes
Inline
Side-by-side
Lottokone/App.config
View file @
1ad184e4
...
...
@@ -14,7 +14,19 @@
<
value
>
100000
</
value
>
</
setting
>
<
setting
name
=
"Riveja"
serializeAs
=
"String"
>
<
value
>
5
</
value
>
<
value
>
3
</
value
>
</
setting
>
<
setting
name
=
"Voimassa"
serializeAs
=
"String"
>
<
value
>
6
</
value
>
</
setting
>
<
setting
name
=
"Nimi"
serializeAs
=
"String"
>
<
value
>
Veikkaaja
</
value
>
</
setting
>
<
setting
name
=
"Arparivit"
serializeAs
=
"String"
>
<
value
>
10
</
value
>
</
setting
>
<
setting
name
=
"ArparivitVoimassa"
serializeAs
=
"String"
>
<
value
>
6
</
value
>
</
setting
>
</
Lottokone
.
Properties
.
Settings
>
</
userSettings
>
...
...
Lottokone/App.xaml
View file @
1ad184e4
...
...
@@ -4,6 +4,17 @@
xmlns:local="clr-namespace:Lottokone"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!-- Globaaleja tyylejä eri kontrolleille -->
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
<Setter Property="FontSize" Value="10" />
</Style>
<!-- Erikseen Style-propertyn käyttä käytettävät tyylit -->
<Style TargetType="TextBox" x:Key="Asetusboksi">
<Setter Property="DockPanel.Dock" Value="Right" />
<Setter Property="Width" Value="150" />
<Setter Property="Margin" Value="5" />
</Style>
</Application.Resources>
</Application>
Lottokone/Asetukset.xaml
View file @
1ad184e4
...
...
@@ -5,37 +5,63 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Lottokone"
mc:Ignorable="d"
Title="Asetukset" Height="450" Width="
80
0">
Title="Asetukset" Height="450" Width="
65
0">
<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal" x:Name="spSettings">
<StackPanel Width="300">
<Label FontWeight="Bold">Simulaation asetukset</Label>
<StackPanel>
<
Sta
ckPanel Margin="5"
Orientation="Horizontal"
>
<
Do
ckPanel Margin="5">
<Label>Pelaajia</Label>
<TextBox
Margin="5
" x:Name="txbPelaajia" Text="{Binding Pelaajia, Mode=TwoWay}"
Width="150"
/>
</
Sta
ckPanel>
<
Label
Margin="25,-5,0,0"
FontSize="10"
>Simulaatiossa käytettävien pelaajien määrä.</
Label
>
<TextBox
Style="{StaticResource Asetusboksi}
" x:Name="txbPelaajia" Text="{Binding Pelaajia, Mode=TwoWay}" />
</
Do
ckPanel>
<
TextBlock
Margin="25,-5,0,0">Simulaatiossa käytettävien pelaajien määrä.</
TextBlock
>
</StackPanel>
<StackPanel>
<
Sta
ckPanel Margin="5"
Orientation="Horizontal"
>
<
Do
ckPanel Margin="5">
<Label>Rivejä</Label>
<TextBox
Margin="5
" x:Name="txbRiveja" Text="{Binding Riveja, Mode=TwoWay}"
Width="150"
/>
</
Sta
ckPanel>
<
Label
Margin="25,-5,0,0"
FontSize="10"
>Simuloitujen pelaajien rivien määrä per pelaaja.</
Label
>
<TextBox
Style="{StaticResource Asetusboksi}
" x:Name="txbRiveja" Text="{Binding Riveja, Mode=TwoWay}" />
</
Do
ckPanel>
<
TextBlock
Margin="25,-5,0,0">Simuloitujen pelaajien rivien määrä per pelaaja.</
TextBlock
>
</StackPanel>
</StackPanel>
<StackPanel>
<DockPanel Margin="5">
<Label>Rivit voimassa</Label>
<TextBox Style="{StaticResource Asetusboksi}" x:Name="txbVoimassa" Text="{Binding Voimassa, Mode=TwoWay}" />
</DockPanel>
<TextBlock Margin="25,-5,0,0">Kuinka monta kierrosta simuloitujen pelaajien rivit pysyvät voimassa, kunnes ne arvotaan uudelleen.</TextBlock>
</StackPanel>
</StackPanel>
<StackPanel>
<Label FontWeight="Bold">Omat
rivi
t</Label>
<Label FontWeight="Bold">Omat
asetukse
t</Label>
<StackPanel>
<StackPanel Orientation="Horizontal">
<DockPanel Margin="5">
<Label>Nimi</Label>
<TextBox Style="{StaticResource Asetusboksi}" x:Name="txbNimi" Text="{Binding Nimi, Mode=TwoWay}" />
</DockPanel>
<TextBlock Margin="25,-5,0,0">Tallennetaan high scoreen, jos joskus muka voitat päävoiton.</TextBlock>
</StackPanel>
<StackPanel>
<DockPanel Margin="5">
<Label>Arparivejä</Label>
<TextBox Style="{StaticResource Asetusboksi}" x:Name="txbArparivit" Text="{Binding Arparivit, Mode=TwoWay}" />
</DockPanel>
<TextBlock Margin="25,-5,0,0">Kuinka monta satunnaisesti arvottua riviä haluat pitää</TextBlock>
</StackPanel>
<StackPanel>
<DockPanel Margin="5">
<Label>Arparivit voimassa</Label>
<TextBox Style="{StaticResource Asetusboksi}" x:Name="txbArparivitVoimassa" Text="{Binding ArparivitVoimassa, Mode=TwoWay}" />
</DockPanel>
<TextBlock Margin="25,-5,0,0">Kuinka monen kierroksen välein rivisi arvotaan uudelleen?</TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</StackPanel>
<Button x:Name="btnSave" Content="Tallenna & sulje" Click="btnSave_Click" Margin="15" />
...
...
Lottokone/MainWindow.xaml
View file @
1ad184e4
...
...
@@ -19,8 +19,8 @@
<Label Content="{Binding Vuosi}" />
<Label Content="Viikko:"/>
<Label Content="{Binding Viikko}" />
<Label Content="
Pelaajia
:"/>
<Label Content="{Binding
Pelaaja
maara}"/>
<Label Content="
Rivejä
:"/>
<Label Content="{Binding
Rivi
maara}"/>
<Label Content="Potti:"/>
<Label Content="{Binding Potti}"/>
<Label Content="Voittorivi:"/>
...
...
Lottokone/Model/Lotto.cs
View file @
1ad184e4
...
...
@@ -4,9 +4,11 @@ using System.Collections.Concurrent;
using
System.Collections.Generic
;
using
System.Collections.ObjectModel
;
using
System.ComponentModel
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Runtime.CompilerServices
;
using
System.Text
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -16,6 +18,26 @@ namespace Lottokone.Model
{
private
bool
kaynnissa
=
false
;
// Mitataan kunkin kierroksen kesto, jotta
// osataan näyttää nättiä statistiikkaa.
private
Stopwatch
stopwatch
;
// Kolme eri listaa eri voittotasoille:
// 5, 6 ja 7 oikein.
// Näihin laitetaan joka kierroksella voittaneet pelaajat,
// ja sitten jaetaan niistä tarkistuksen jälkeen voitot.
//
// Pienempiä voittotasoja ei tarvitse listata, koska niiden voittosumma
// ei riipu voittajien määristä vaan on aina sama. Ne voidaan hoitaa helpommin.
//
// Olisin mielummin toteuttanut tämän indeksoituna listana:
// eli oikein[5] takaa löytyisi lista viisi oikein pelaajista, jne..
// Parallelismin kannalta tämä oli kuitenkin hankalaa, ja valmiiden
// thread-safe ConcurrentBagien käyttö on järkevämpää, vaikkakin rumaa.
private
ConcurrentBag
<
Pelaaja
>
oikein5
;
private
ConcurrentBag
<
Pelaaja
>
oikein6
;
private
ConcurrentBag
<
Pelaaja
>
oikein7
;
private
short
viikko
;
public
short
Viikko
{
...
...
@@ -51,18 +73,8 @@ namespace Lottokone.Model
public
ConcurrentBag
<
Pelaaja
>
Pelaajat
{
get
;
set
;
}
// neljä listaa eri voittotasoille:
// 4 oikein, 5 oikein, 6 oikein ja 7 oikein
// nämä olisi voinut periaatteessa asettaa listaan, ja
// käyttää indeksin kautta (oikein[5] olisi lista viisi oikein -tuloksista jne.)
// mutta se aiheuttaisi threadingin kanssa ongelmia.
public
ConcurrentBag
<
Pelaaja
>
Oikein4
{
get
;
set
;
}
public
ConcurrentBag
<
Pelaaja
>
Oikein5
{
get
;
set
;
}
public
ConcurrentBag
<
Pelaaja
>
Oikein6
{
get
;
set
;
}
public
ConcurrentBag
<
Pelaaja
>
Oikein7
{
get
;
set
;
}
private
long
potti
;
public
long
Potti
private
int
potti
;
public
int
Potti
{
get
{
...
...
@@ -105,13 +117,17 @@ namespace Lottokone.Model
}
}
// pelaajamäärä pitää pitää inttinä, niin saadaan helposti bindattua se
// käyttöliittymän puolella.
public
int
Pelaajamaara
// Lasketaan kierroksella mukana olleiden rivien määrä.
public
int
Rivimaara
{
get
{
return
Pelaajat
.
Count
();
int
n
=
0
;
foreach
(
Pelaaja
p
in
Pelaajat
)
{
n
+=
p
.
Rivit
.
Count
();
}
return
n
;
}
}
...
...
@@ -121,12 +137,13 @@ namespace Lottokone.Model
viikko
=
0
;
vuosi
=
1
;
Pelaajat
=
new
ConcurrentBag
<
Pelaaja
>();
Voittorivi
=
new
Voittorivi
();
StatusHistory
=
new
ObservableCollectionEx
<
string
>(
new
List
<
String
>());
StatusHistory
=
new
ObservableCollectionEx
<
string
>(
new
List
<
string
>());
Status
=
"Veikkaus: Pelaa maltillisesti :):):):)"
;
stopwatch
=
Stopwatch
.
StartNew
();
LisaaPelaajia
(
Properties
.
Settings
.
Default
.
Pelaajia
,
Properties
.
Settings
.
Default
.
Riveja
);
stopwatch
.
Stop
();
Status
=
$"Lisätty
{
Pelaajat
.
Count
()}
pelaajaa (
{
stopwatch
.
ElapsedMilliseconds
}
ms)"
;
}
public
void
LisaaPelaajia
(
int
pelaajia
,
int
riveja
)
...
...
@@ -149,28 +166,30 @@ namespace Lottokone.Model
public
void
Tick
()
{
stopwatch
.
Reset
();
stopwatch
.
Start
();
Viikko
++;
Oikein4
=
new
ConcurrentBag
<
Pelaaja
>();
Oikein5
=
new
ConcurrentBag
<
Pelaaja
>();
Oikein6
=
new
ConcurrentBag
<
Pelaaja
>();
Oikein7
=
new
ConcurrentBag
<
Pelaaja
>();
oikein5
=
new
ConcurrentBag
<
Pelaaja
>();
oikein6
=
new
ConcurrentBag
<
Pelaaja
>();
oikein7
=
new
ConcurrentBag
<
Pelaaja
>();
// Uusi voittorivi ei jostain syystä päivity UI:hin,
// ellei sitä alusta kokonaan uudelleen täällä.
Voittorivi
=
new
Voittorivi
();
Voittorivi
.
ArvoRivi
();
EtsiVoittajat
();
Status
=
$"-Viikko
{
Viikko
}
-"
;
if
(!
Oikein4
.
IsEmpty
)
Status
=
$"4 oikein:
{
Oikein4
.
Count
()}
"
;
if
(!
Oikein5
.
IsEmpty
)
Status
=
$"5 oikein:
{
Oikein5
.
Count
()}
"
;
if
(!
Oikein6
.
IsEmpty
)
Status
=
$"6 oikein:
{
Oikein6
.
Count
()}
"
;
if
(!
Oikein7
.
IsEmpty
)
Status
=
$"7 oikein:
{
Oikein7
.
Count
()}
"
;
//JaaVoitot();
JaaVoitot
();
stopwatch
.
Stop
();
Status
=
$"-Viikko
{
Viikko
}
(
{
stopwatch
.
ElapsedMilliseconds
}
ms)-"
;
}
// Voittajat täytyy erikseen etsiä ja sitten vasta jakaa voitot.
// Samassa loopissa niitä ei voi tehdä, koska voittosumma riippuu voittajien
// määrästä. Se on selvillä vasta kun kaikki on käyty läpi.
private
void
EtsiVoittajat
()
{
Parallel
.
ForEach
(
Pelaajat
,
(
p
)
=>
...
...
@@ -182,16 +201,23 @@ namespace Lottokone.Model
switch
(
r
.
Oikein
(
Voittorivi
))
{
case
4
:
Oikein4
.
Add
(
p
);
// 4 oikein on tasan 10e voitto, joten se voidaan jakaa täällä.
// pottia voi käsitellä useampi säie samaan aikaan,
// siksi System.Threading.Interlocked.Add, joka on atominen operaatio
Interlocked
.
Add
(
ref
potti
,
-
10
);
// tätä pelaajaa taas ei käsitellä kuin me tässä ja nyt.
p
.
Saldo
+=
10
;
break
;
case
5
:
O
ikein5
.
Add
(
p
);
o
ikein5
.
Add
(
p
);
break
;
case
6
:
O
ikein6
.
Add
(
p
);
o
ikein6
.
Add
(
p
);
break
;
case
7
:
O
ikein7
.
Add
(
p
);
o
ikein7
.
Add
(
p
);
break
;
default
:
break
;
...
...
@@ -201,21 +227,46 @@ namespace Lottokone.Model
}
// https://fi.wikipedia.org/wiki/Lotto_(Veikkaus)#Voittoluokat_ja_voiton_todenn%C3%A4k%C3%B6isyys
// 3+1: 2 e (todo)
// 4 oikein: 10 e
// 5 oikein: 3% potista voittajien kesken
// 6 oikein: 2,5% potista voittajien kesken
// 6+1: 3,8% potista voittajien kesken
// 6+1: 3,8% potista voittajien kesken
(todo)
// 7: päävoitto
// Luotetaan, että aiemmat tarkistukset on oikein, eikä
// listoilla ole pelaajia joiden rivit eivät ole voittaneet...
private
void
JaaVoitot
()
{
Task
neljat
=
Task
.
Run
(()
=>
if
(!
oikein5
.
IsEmpty
)
{
Pelaaja
p
;
while
(
Oikein4
.
TryTake
(
out
p
)
!=
false
)
int
voittajia
=
oikein5
.
Count
();
int
voitto
=
((
potti
/
100
)
*
3
)
/
voittajia
;
Status
=
$"5 oikein voittoja
{
voittajia
}
kpl (
{
voitto
}
e)"
;
while
(
oikein5
.
TryTake
(
out
Pelaaja
p
)
!=
false
)
{
p
.
Saldo
+=
voitto
;
}
}
if
(!
oikein6
.
IsEmpty
)
{
int
voittajia
=
oikein6
.
Count
();
int
voitto
=
(
int
)((
potti
/
100
)
*
2.5
)
/
voittajia
;
Status
=
$"6 oikein voittoja
{
voittajia
}
kpl (
{
voitto
}
e)"
;
while
(
oikein6
.
TryTake
(
out
Pelaaja
p
)
!=
false
)
{
p
.
Saldo
+=
voitto
;
}
});
}
if
(!
oikein7
.
IsEmpty
)
{
int
voittajia
=
oikein7
.
Count
();
int
voitto
=
(
int
)((
potti
/
100
)
*
60
)
/
voittajia
;
Status
=
$"!!! 7 oikein!
{
voitto
}
e (
{
voittajia
}
kpl) !!!"
;
}
}
protected
void
RaisePropertyChanged
([
CallerMemberName
]
string
propertyName
=
null
)
...
...
Lottokone/Model/Pelaaja.cs
View file @
1ad184e4
...
...
@@ -34,14 +34,18 @@ namespace Lottokone.Model
public
void
Tick
()
{
// Käydään rivit takaperin läpi, niin voidaan tarvittaessa
// poistaa indeksistä jossa ollaan ja jatkaa looppia turvallisesti.
for
(
int
i
=
Rivit
.
Count
()
-
1
;
i
>
0
;
i
--)
{
Saldo
--;
Lottorivi
r
=
Rivit
[
i
];
r
.
Voimassa
--;
if
(
r
.
Voimassa
<
0
)
Rivit
.
Remove
(
r
);
}
// Luodaan uusia arparivejä tarpeen mukaan
int
ero
=
Riveja
-
Rivit
.
Count
();
if
(
ero
>
0
)
for
(
int
i
=
0
;
i
<
ero
;
i
++)
...
...
Lottokone/Properties/Settings.Designer.cs
View file @
1ad184e4
...
...
@@ -12,7 +12,7 @@ namespace Lottokone.Properties {
[
global
::
System
.
Runtime
.
CompilerServices
.
CompilerGeneratedAttribute
()]
[
global
::
System
.
CodeDom
.
Compiler
.
GeneratedCodeAttribute
(
"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator"
,
"15.
7
.0.0"
)]
[
global
::
System
.
CodeDom
.
Compiler
.
GeneratedCodeAttribute
(
"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator"
,
"15.
9
.0.0"
)]
internal
sealed
partial
class
Settings
:
global
::
System
.
Configuration
.
ApplicationSettingsBase
{
private
static
Settings
defaultInstance
=
((
Settings
)(
global
::
System
.
Configuration
.
ApplicationSettingsBase
.
Synchronized
(
new
Settings
())));
...
...
@@ -37,7 +37,7 @@ namespace Lottokone.Properties {
[
global
::
System
.
Configuration
.
UserScopedSettingAttribute
()]
[
global
::
System
.
Diagnostics
.
DebuggerNonUserCodeAttribute
()]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"
5
"
)]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"
3
"
)]
public
int
Riveja
{
get
{
return
((
int
)(
this
[
"Riveja"
]));
...
...
@@ -46,5 +46,53 @@ namespace Lottokone.Properties {
this
[
"Riveja"
]
=
value
;
}
}
[
global
::
System
.
Configuration
.
UserScopedSettingAttribute
()]
[
global
::
System
.
Diagnostics
.
DebuggerNonUserCodeAttribute
()]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"6"
)]
public
int
Voimassa
{
get
{
return
((
int
)(
this
[
"Voimassa"
]));
}
set
{
this
[
"Voimassa"
]
=
value
;
}
}
[
global
::
System
.
Configuration
.
UserScopedSettingAttribute
()]
[
global
::
System
.
Diagnostics
.
DebuggerNonUserCodeAttribute
()]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"Veikkaaja"
)]
public
string
Nimi
{
get
{
return
((
string
)(
this
[
"Nimi"
]));
}
set
{
this
[
"Nimi"
]
=
value
;
}
}
[
global
::
System
.
Configuration
.
UserScopedSettingAttribute
()]
[
global
::
System
.
Diagnostics
.
DebuggerNonUserCodeAttribute
()]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"10"
)]
public
int
Arparivit
{
get
{
return
((
int
)(
this
[
"Arparivit"
]));
}
set
{
this
[
"Arparivit"
]
=
value
;
}
}
[
global
::
System
.
Configuration
.
UserScopedSettingAttribute
()]
[
global
::
System
.
Diagnostics
.
DebuggerNonUserCodeAttribute
()]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"6"
)]
public
int
ArparivitVoimassa
{
get
{
return
((
int
)(
this
[
"ArparivitVoimassa"
]));
}
set
{
this
[
"ArparivitVoimassa"
]
=
value
;
}
}
}
}
Lottokone/Properties/Settings.settings
View file @
1ad184e4
...
...
@@ -6,7 +6,19 @@
<Value
Profile=
"(Default)"
>
100000
</Value>
</Setting>
<Setting
Name=
"Riveja"
Type=
"System.Int32"
Scope=
"User"
>
<Value
Profile=
"(Default)"
>
5
</Value>
<Value
Profile=
"(Default)"
>
3
</Value>
</Setting>
<Setting
Name=
"Voimassa"
Type=
"System.Int32"
Scope=
"User"
>
<Value
Profile=
"(Default)"
>
6
</Value>
</Setting>
<Setting
Name=
"Nimi"
Type=
"System.String"
Scope=
"User"
>
<Value
Profile=
"(Default)"
>
Veikkaaja
</Value>
</Setting>
<Setting
Name=
"Arparivit"
Type=
"System.Int32"
Scope=
"User"
>
<Value
Profile=
"(Default)"
>
10
</Value>
</Setting>
<Setting
Name=
"ArparivitVoimassa"
Type=
"System.Int32"
Scope=
"User"
>
<Value
Profile=
"(Default)"
>
6
</Value>
</Setting>
</Settings>
</SettingsFile>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment