Commit 4911110e authored by M1888's avatar M1888

viimeiset muutokset

parent 4fc40862
...@@ -23,17 +23,21 @@ namespace Lottokone ...@@ -23,17 +23,21 @@ namespace Lottokone
public Asetukset() public Asetukset()
{ {
InitializeComponent(); InitializeComponent();
// sidotaan asetukset ikkunaan
spSettings.DataContext = Properties.Settings.Default; spSettings.DataContext = Properties.Settings.Default;
} }
private void btnSave_Click(object sender, RoutedEventArgs e) private void btnSave_Click(object sender, RoutedEventArgs e)
{ {
// tallennetaan asetukset ja suljetaan ikkuna
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();
this.Close(); this.Close();
} }
private void BtnRivit_Click(object sender, RoutedEventArgs e) private void BtnRivit_Click(object sender, RoutedEventArgs e)
{ {
// lottorivit-ikkuna aukeaa uutena dialogina
new Lottorivit().ShowDialog(); new Lottorivit().ShowDialog();
} }
public void txbChanged(object sender, TextChangedEventArgs e) public void txbChanged(object sender, TextChangedEventArgs e)
...@@ -91,6 +95,8 @@ namespace Lottokone ...@@ -91,6 +95,8 @@ namespace Lottokone
private void TxbVakiorivit_TextChanged(object sender, TextChangedEventArgs e) private void TxbVakiorivit_TextChanged(object sender, TextChangedEventArgs e)
{ {
// vakiorivit pitää validoida erikseen, jotta voidaan säätää vakiorivien säädön
// ikkunan avaavan napin aktiivisuutta samalla.
TextBox tb = sender as TextBox; TextBox tb = sender as TextBox;
if(tb != null) if(tb != null)
{ {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Lottokone" xmlns:local="clr-namespace:Lottokone"
mc:Ignorable="d" mc:Ignorable="d"
Title="Lottokone" Height="450" Width="950" Background="Black"> Title="Lottokone" Height="450" Width="960" Background="Black">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel Margin="5,10,5,0"> <StackPanel Margin="5,10,5,0">
<Button x:Name="btnNext" Margin="0,5,0,0" Content="Seuraava viikko" Click="btnNext_Click"/> <Button x:Name="btnNext" Margin="0,5,0,0" Content="Seuraava viikko" Click="btnNext_Click"/>
......
...@@ -36,13 +36,11 @@ namespace Lottokone ...@@ -36,13 +36,11 @@ namespace Lottokone
private ObservableCollection<string> voitot; private ObservableCollection<string> voitot;
private object voittolukko; private object voittolukko;
// Tämä ajaa meidän pelilooppia kun starttia painetaan
private Thread runner;
private bool kaynnissa = false;
// tähän tallennetaan oletuksena imgLotto-kuvassa oleva kuva. // tähän tallennetaan oletuksena imgLotto-kuvassa oleva kuva.
// Se voidaan sitten helposti palauttaa, kun ollaan hetki näytetty jotain muuta kuvaa // Se voidaan sitten helposti palauttaa, kun ollaan hetki näytetty jotain muuta kuvaa
private ImageSource oletuskuva; private ImageSource oletuskuva;
// eri voittoluokkien kuvat, ja laskuri joka kertoo missä kuvassa ollaan menossa.
private BitmapImage img5oikein; private BitmapImage img5oikein;
private BitmapImage img6oikein; private BitmapImage img6oikein;
private BitmapImage img7oikein; private BitmapImage img7oikein;
...@@ -51,9 +49,23 @@ namespace Lottokone ...@@ -51,9 +49,23 @@ namespace Lottokone
// Tällä katsotaan, joko kuva pitäisi vaihtaa takaisin oletukseen. // Tällä katsotaan, joko kuva pitäisi vaihtaa takaisin oletukseen.
private Stopwatch kuvakello; private Stopwatch kuvakello;
// Tässä kyseinen pelilooppi // Tämä ajaa meidän pelilooppia kun starttia painetaan
private Thread runner;
private bool kaynnissa = false;
// konstruktori
public MainWindow()
{
InitializeComponent();
InitializeLottokone();
}
// Tässä yllä mainittu pelilooppi.
// Tämä olisi ollut ehkä järkevä toteuttaa muualla kuin täällä MainWindow.xaml.cs:ssä, // Tämä olisi ollut ehkä järkevä toteuttaa muualla kuin täällä MainWindow.xaml.cs:ssä,
// mutta tällä nyt mennään.... // mutta tällä nyt mennään....
//
// Itse lottokone ja sen simulaatio toimii siis ilman tätäkin pelilooppia, vaikka toisessa ohjelmassa:
// Tämä pitää vain huolen meidän pelaajasta, joka on simulaatiossa mukana.
private void GameLoop() private void GameLoop()
{ {
do do
...@@ -63,6 +75,8 @@ namespace Lottokone ...@@ -63,6 +75,8 @@ namespace Lottokone
// saadaan niistä tieto myös toiseen listaikkunaan. // saadaan niistä tieto myös toiseen listaikkunaan.
foreach (Lottorivi r in pelaaja.Rivit) foreach (Lottorivi r in pelaaja.Rivit)
{ {
// tähän stringiin tallennetaan pelaajan voittoikkunaan tuleva teksti,
// jos sellaista on.
string s = ""; string s = "";
switch (r.Oikein(kone.Voittorivi)) switch (r.Oikein(kone.Voittorivi))
{ {
...@@ -138,10 +152,15 @@ namespace Lottokone ...@@ -138,10 +152,15 @@ namespace Lottokone
{ {
s = $"Pisteiden talletus tietokantaan ei onnistunut: ${ex.Message}"; s = $"Pisteiden talletus tietokantaan ei onnistunut: ${ex.Message}";
} }
// Avataan voitto-ikkuna
new Voitto().Show();
break; break;
default: default:
break; break;
} }
// Asetetaan uusi teksti voitot-ikkunaan, jos tarve.
if (s.Length > 0) if (s.Length > 0)
{ {
lock (voittolukko) lock (voittolukko)
...@@ -168,10 +187,10 @@ namespace Lottokone ...@@ -168,10 +187,10 @@ namespace Lottokone
} while (kaynnissa); } while (kaynnissa);
} }
public MainWindow()
{
InitializeComponent();
// Alustetaan lottokone ja pelaaja ja kaikki muu tarvittava.
public void InitializeLottokone()
{
// tällä saadaan käyttöliittymässä luvut ja rahamäärät näkymään oikein. // tällä saadaan käyttöliittymässä luvut ja rahamäärät näkymään oikein.
// https://stackoverflow.com/questions/7454024/setting-culture-en-in-globally-in-wpf-app // https://stackoverflow.com/questions/7454024/setting-culture-en-in-globally-in-wpf-app
var culture = new CultureInfo("fi-FI"); var culture = new CultureInfo("fi-FI");
...@@ -188,6 +207,8 @@ namespace Lottokone ...@@ -188,6 +207,8 @@ namespace Lottokone
// status-ikkunaan skrollaava historia eventeistä // status-ikkunaan skrollaava historia eventeistä
// EnableCollectionSynchronization() mahdollistaa listan käyttämisen muista // EnableCollectionSynchronization() mahdollistaa listan käyttämisen muista
// threadeista, ja UI-thread saa siitä silti CollectionUpdated eventin. // threadeista, ja UI-thread saa siitä silti CollectionUpdated eventin.
// Lukko-objekti annetaan sitä varten, ettei UI thread mene sörkkimään listaa sillä aikaa
// kun me lisätään sinne asioita toisesta threadista.
BindingOperations.EnableCollectionSynchronization(kone.StatusHistory, kone.StatusLock); BindingOperations.EnableCollectionSynchronization(kone.StatusHistory, kone.StatusLock);
lstStatus.ItemsSource = kone.StatusHistory; lstStatus.ItemsSource = kone.StatusHistory;
...@@ -285,23 +306,29 @@ namespace Lottokone ...@@ -285,23 +306,29 @@ namespace Lottokone
private void btnSettings_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e)
{ {
var a = new Asetukset(); new Asetukset().ShowDialog();
a.ShowDialog();
// kun asetuksista palataan, voidaan ottaa uudet asetukset käyttöön. // kun asetuksista palataan, voidaan ottaa uudet asetukset käyttöön.
// ensin tarkistetaan, onko pelaajamäärä muuttunut // Ensin otetaan "keskivertopelaaja" jostain meidän listan keskivälistä.
// Kunhan tarvittavat pelaajat on sitten saatu lisättyä tai poistettua, saadaan
// verrattua vanhojen pelaajien tietoja tähän keskivertojäbään. Jos muutoksia tarvitaan,
// niin sitten tehdään ne.
// ConcurrentBag ei sinänsä takaa elementtien järjestystä mitenkään, ja me ollaan lisätty
// meidän pelaaja tänne luultavasti viimeisimpänä joten se voi olla ensimmäisenä tai viimeisenä.
// Tuskin kuitenkaan keskellä.
Pelaaja tmp = kone.Pelaajat.ElementAt(kone.Pelaajat.Count() / 2);
// Tarkistetaan, onko pelaajamäärä muuttunut
int curr = kone.Pelaajat.Count(); int curr = kone.Pelaajat.Count();
// + 1 koska pelaajissa on myös meidän pelaajaolio // Asetusten pelaajiin pitää lisätä vielä 1 koska pelaajissa on myös meidän pelaajaolio
int uusi = Properties.Settings.Default.Pelaajia + 1; int uusi = Properties.Settings.Default.Pelaajia + 1;
if (curr < uusi) if (curr < uusi)
kone.LisaaPelaajia(uusi - curr, Properties.Settings.Default.Riveja); kone.LisaaPelaajia(uusi - curr, Properties.Settings.Default.Riveja);
else if (curr > uusi) else if (curr > uusi)
kone.PoistaPelaajia(curr - uusi); kone.PoistaPelaajia(curr - uusi);
// otetaan joku satunnainen pelaaja, ja verrataan sen tietoja uusiin.
// Näin saadaan selville, pitääkö pelaajien tietoja muuttaa.
Pelaaja tmp = kone.Pelaajat.ElementAt(kone.Pelaajat.Count() / 2);
if (tmp.RivitVoimassa != Properties.Settings.Default.Voimassa) if (tmp.RivitVoimassa != Properties.Settings.Default.Voimassa)
{ {
kone.Status = $"Rivit voimassa {tmp.RivitVoimassa} -> {Properties.Settings.Default.Voimassa} viikkoa"; kone.Status = $"Rivit voimassa {tmp.RivitVoimassa} -> {Properties.Settings.Default.Voimassa} viikkoa";
......
...@@ -20,6 +20,9 @@ namespace Lottokone.Model ...@@ -20,6 +20,9 @@ namespace Lottokone.Model
// osataan näyttää nättiä statistiikkaa. // osataan näyttää nättiä statistiikkaa.
private Stopwatch stopwatch; private Stopwatch stopwatch;
// Lista lottokoneen pelaajista
public ConcurrentBag<Pelaaja> Pelaajat { get; set; }
// Neljä eri listaa eri voittotasoille: // Neljä eri listaa eri voittotasoille:
// 5, 6, 6+1 ja 7 oikein. // 5, 6, 6+1 ja 7 oikein.
// Näihin laitetaan joka kierroksella voittaneet pelaajat, // Näihin laitetaan joka kierroksella voittaneet pelaajat,
...@@ -37,6 +40,9 @@ namespace Lottokone.Model ...@@ -37,6 +40,9 @@ namespace Lottokone.Model
private ConcurrentBag<Pelaaja> oikein6_1; private ConcurrentBag<Pelaaja> oikein6_1;
private ConcurrentBag<Pelaaja> oikein7; private ConcurrentBag<Pelaaja> oikein7;
// Viikolla on laskin, joka nostaa myös vuosia.
// Lottokoneen loopissa voidaan siis vaan kutsua Viikko++,
// ja kun vuosi tulee täyteen, alkaa viikot alusta automaattisesti.
private short viikko; private short viikko;
public short Viikko public short Viikko
{ {
...@@ -56,6 +62,7 @@ namespace Lottokone.Model ...@@ -56,6 +62,7 @@ namespace Lottokone.Model
} }
} }
// monesko vuosi on menossa
private short vuosi; private short vuosi;
public short Vuosi public short Vuosi
{ {
...@@ -70,6 +77,7 @@ namespace Lottokone.Model ...@@ -70,6 +77,7 @@ namespace Lottokone.Model
} }
} }
// Kuinka mones kierros on menossa?
public int Kierros public int Kierros
{ {
get get
...@@ -78,7 +86,6 @@ namespace Lottokone.Model ...@@ -78,7 +86,6 @@ namespace Lottokone.Model
} }
} }
public ConcurrentBag<Pelaaja> Pelaajat { get; set; }
// Nämä voi olla pelkkiä listoja, koska threadeissa vain lueataan niistä. // Nämä voi olla pelkkiä listoja, koska threadeissa vain lueataan niistä.
public List<string> Etunimet { get; set; } public List<string> Etunimet { get; set; }
...@@ -95,6 +102,7 @@ namespace Lottokone.Model ...@@ -95,6 +102,7 @@ namespace Lottokone.Model
} }
} }
// Joka kierroksella jaossa oleva potti
private int potti; private int potti;
public int Potti public int Potti
{ {
...@@ -111,6 +119,7 @@ namespace Lottokone.Model ...@@ -111,6 +119,7 @@ namespace Lottokone.Model
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
// Kierroksen voittorivi
private Voittorivi voittorivi; private Voittorivi voittorivi;
public Voittorivi Voittorivi public Voittorivi Voittorivi
{ {
...@@ -207,15 +216,15 @@ namespace Lottokone.Model ...@@ -207,15 +216,15 @@ namespace Lottokone.Model
{ {
Status = $"Nimien lataus epäonnistui: {ex.Message}"; Status = $"Nimien lataus epäonnistui: {ex.Message}";
} }
stopwatch.Stop();
Status = $"Alustettu lottokone ({stopwatch.ElapsedMilliseconds}ms)";
// LisaaPelaajia hoitaa kellon pysäytyksen
LisaaPelaajia(Properties.Settings.Default.Pelaajia, Properties.Settings.Default.Riveja); LisaaPelaajia(Properties.Settings.Default.Pelaajia, Properties.Settings.Default.Riveja);
} }
public void LisaaPelaajia(int pelaajia, int riveja) public void LisaaPelaajia(int pelaajia, int riveja)
{ {
// Ei nollata kelloa tämän alussa, niin saadaan aika ohjelman käynnistyksestä paremmin. stopwatch.Restart();
stopwatch.Start();
//for (int i = 0; i < pelaajia; i++) //for (int i = 0; i < pelaajia; i++)
Parallel.For(0, pelaajia, Parallel.For(0, pelaajia,
...@@ -237,10 +246,10 @@ namespace Lottokone.Model ...@@ -237,10 +246,10 @@ namespace Lottokone.Model
Status = $"Poistettu {maara} pelaajaa ({stopwatch.ElapsedMilliseconds}ms)"; Status = $"Poistettu {maara} pelaajaa ({stopwatch.ElapsedMilliseconds}ms)";
} }
// Tämä metodi edistää lottokoneen simulaatiota viikolla.
public void Tick() public void Tick()
{ {
stopwatch.Restart(); stopwatch.Restart();
Viikko++; Viikko++;
// Tyhjennetään voittajien listat vain jos viime kierroksella oli voittajia. // Tyhjennetään voittajien listat vain jos viime kierroksella oli voittajia.
...@@ -254,17 +263,26 @@ namespace Lottokone.Model ...@@ -254,17 +263,26 @@ namespace Lottokone.Model
if (!oikein7.IsEmpty) if (!oikein7.IsEmpty)
oikein7 = new ConcurrentBag<Pelaaja>(); oikein7 = new ConcurrentBag<Pelaaja>();
// Arvotaan uusi voittorivi
Voittorivi = new Voittorivi(); Voittorivi = new Voittorivi();
// Etsitään voitot (tämä kutsuu myös pelaajien Pelaaja.Tick() metodia,
// joka päivittää lottorivit ja arpoo ne tarvittaessa uudelleen,
// sekä päivittää pelaajien saldot.
EtsiVoittajat(); EtsiVoittajat();
// Rivimäärä on laskettu ominaisuus, johon ei aseteta suoraan mitään arvoa.
// Kun se päviittyy, pitää siitä kertoa UI:lle, jonne luku on sidottu.
RaisePropertyChanged("Rivimaara"); RaisePropertyChanged("Rivimaara");
// Lasketaan kierroksen uusi potti
Potti = (int)(Rivimaara * Properties.Settings.Default.Rivihinta); Potti = (int)(Rivimaara * Properties.Settings.Default.Rivihinta);
// Lopuksi jaetaan kierroksen voitot
JaaVoitot(); JaaVoitot();
stopwatch.Stop();
stopwatch.Stop();
Status = $"-Kierros {Kierros} ({stopwatch.ElapsedMilliseconds}ms)-"; Status = $"-Kierros {Kierros} ({stopwatch.ElapsedMilliseconds}ms)-";
} }
// Voittajat täytyy erikseen etsiä ja sitten vasta jakaa voitot. // Voittajat täytyy erikseen etsiä ja sitten vasta jakaa voitot.
...@@ -331,11 +349,15 @@ namespace Lottokone.Model ...@@ -331,11 +349,15 @@ namespace Lottokone.Model
// listoilla ole pelaajia joiden rivit eivät ole voittaneet... // listoilla ole pelaajia joiden rivit eivät ole voittaneet...
private void JaaVoitot() private void JaaVoitot()
{ {
// lasketaan prosentit voitoille alkuperäisestä potista, vaikka
// voittoja jakaessa jo vähennetään kierroksen oikeasta potista.
int alkupotti = potti;
if (!oikein5.IsEmpty) if (!oikein5.IsEmpty)
{ {
int voittajia = oikein5.Count(); int voittajia = oikein5.Count();
voitot[3] = ((potti / 100) * 3) / voittajia; // 3% voittajien kesken
voitot[3] = ((alkupotti / 100) * 3) / voittajia;
Status = $"5 oikein voittoja {voittajia:N0} kpl ({voitot[3]:C0})"; Status = $"5 oikein voittoja {voittajia:N0} kpl ({voitot[3]:C0})";
...@@ -349,7 +371,8 @@ namespace Lottokone.Model ...@@ -349,7 +371,8 @@ namespace Lottokone.Model
if (!oikein6.IsEmpty) if (!oikein6.IsEmpty)
{ {
int voittajia = oikein6.Count(); int voittajia = oikein6.Count();
voitot[2] = (int)((potti / 100) * 2.5) / voittajia; // 2.5% voittajien kesken
voitot[2] = (int)((alkupotti / 100) * 2.5) / voittajia;
Status = $"6 oikein voittoja {voittajia:N0} kpl ({voitot[2]:C0})"; Status = $"6 oikein voittoja {voittajia:N0} kpl ({voitot[2]:C0})";
...@@ -363,7 +386,8 @@ namespace Lottokone.Model ...@@ -363,7 +386,8 @@ namespace Lottokone.Model
if (!oikein6_1.IsEmpty) if (!oikein6_1.IsEmpty)
{ {
int voittajia = oikein6_1.Count(); int voittajia = oikein6_1.Count();
voitot[1] = (int)((potti / 100) * 3.8) / voittajia; // 3.8% voittajien kesken
voitot[1] = (int)((alkupotti / 100) * 3.8) / voittajia;
Status = $"6+1 oikein voittoja {voittajia:N0} kpl ({voitot[1]:C0})"; Status = $"6+1 oikein voittoja {voittajia:N0} kpl ({voitot[1]:C0})";
......
...@@ -122,7 +122,7 @@ namespace Lottokone.Model ...@@ -122,7 +122,7 @@ namespace Lottokone.Model
// Käydään rivit takaperin läpi, niin voidaan tarvittaessa // Käydään rivit takaperin läpi, niin voidaan tarvittaessa
// poistaa indeksistä jossa ollaan ja jatkaa looppia turvallisesti. // poistaa indeksistä jossa ollaan ja jatkaa looppia turvallisesti.
for (int i = Rivit.Count() - 1; i > 0; i--) for (int i = Rivit.Count() - 1; i >= 0; i--)
{ {
Lottorivi r = Rivit[i]; Lottorivi r = Rivit[i];
// jos rivi on tässä vaiheessa nolla viikkoa voimassa, // jos rivi on tässä vaiheessa nolla viikkoa voimassa,
......
...@@ -12,12 +12,14 @@ namespace Lottokone.Model ...@@ -12,12 +12,14 @@ namespace Lottokone.Model
public short[] Numerot { get; set; } public short[] Numerot { get; set; }
public Rivi() public Rivi()
{ {
// oletuksena uusi rivi arvotaan
Numerot = new short[7]; Numerot = new short[7];
ArvoRivi(); ArvoRivi();
} }
public Rivi(short[] numerot) public Rivi(short[] numerot)
{ {
// jos saadaan taulukko numeroita, niin varmistetaan että pituus on oikea.
if (numerot.Length != 7) if (numerot.Length != 7)
throw new ArgumentException("Rivin pituus pitää olla 7 numeroa"); throw new ArgumentException("Rivin pituus pitää olla 7 numeroa");
Numerot = numerot; Numerot = numerot;
...@@ -25,15 +27,16 @@ namespace Lottokone.Model ...@@ -25,15 +27,16 @@ namespace Lottokone.Model
public Rivi(Rivi r) public Rivi(Rivi r)
{ {
// olemassaolevalta riviltä kopioidaan numerot
Numerot = r.Numerot; Numerot = r.Numerot;
} }
public virtual void ArvoRivi() public virtual void ArvoRivi()
{ {
// Otetaan numerot 1-40, järjestellään satunnaisesti, valitaan 7 ekaa, ja tehdään niistä taulukko
// Enumerable.Range tuottaa inttejä, jotka pitää sitten muuntaa shorteiksi
Numerot = Array.ConvertAll( Numerot = Array.ConvertAll(
// otetaan numerot 1-40, järjestellään satunnaisesti, valitaan 7 ekaa, ja tehdään niistä taulukko
Enumerable.Range(1, 40).OrderBy(x => Rand.Next(0, Int32.MaxValue)).Take(7).ToArray(), Enumerable.Range(1, 40).OrderBy(x => Rand.Next(0, Int32.MaxValue)).Take(7).ToArray(),
// Enumerable.Range tuottaa inttejä, jotka pitää sitten muuntaa shorteiksi
Convert.ToInt16); Convert.ToInt16);
// järjestellään rivi arpomisen jälkeen heti // järjestellään rivi arpomisen jälkeen heti
...@@ -52,6 +55,7 @@ namespace Lottokone.Model ...@@ -52,6 +55,7 @@ namespace Lottokone.Model
return Numerot.Intersect(r.Numerot).Count(); return Numerot.Intersect(r.Numerot).Count();
} }
// Jos rivin numerot on täysin samat, niin ne ovat sama rivi.
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
Rivi r = obj as Rivi; Rivi r = obj as Rivi;
......
...@@ -24,7 +24,11 @@ namespace Lottokone ...@@ -24,7 +24,11 @@ namespace Lottokone
public Rikkaimmat(ConcurrentBag<Pelaaja> pelaajat) public Rikkaimmat(ConcurrentBag<Pelaaja> pelaajat)
{ {
InitializeComponent(); InitializeComponent();
// 15 rikkainta listalle
lstRikkaimmat.ItemsSource = pelaajat.OrderByDescending(p => p.Saldo).Take(15); lstRikkaimmat.ItemsSource = pelaajat.OrderByDescending(p => p.Saldo).Take(15);
// scoreboardille tietokannasta rivit.
try try
{ {
dgScoreboard.ItemsSource = ViewModel.Scoreboard.HaePelaajat(); dgScoreboard.ItemsSource = ViewModel.Scoreboard.HaePelaajat();
......
...@@ -13,7 +13,7 @@ namespace Lottokone.ViewModel ...@@ -13,7 +13,7 @@ namespace Lottokone.ViewModel
{ {
public static DataView HaePelaajat() public static DataView HaePelaajat()
{ {
const string sql = "SELECT Pvm, Nimi, Saldo FROM Scoreboard ORDER BY Saldo DESC"; const string sql = "SELECT Nimi, Saldo, Pvm FROM Scoreboard ORDER BY Saldo DESC";
DataSet ds = new DataSet(); DataSet ds = new DataSet();
try try
{ {
......
No preview for this file type
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment