Avatar billede kattendk Nybegynder
14. november 2008 - 21:59 Der er 23 kommentarer og
1 løsning

While en ini fil for stats

Hej Eksperten!

Hvis jeg har en fil maps.ini (mIni.Readini("maps", bane)) og (mIni.Readini("stats", bane)).

I maps.ini står der:
[maps]
de_dust2=de_dust2
de_inferno=de_inferno
[stats]
de_dust2=2
de_inferno=0

Hvordan får jeg så lavet en stats over det, så den skriver på irc automatisk med hvilke baner der står således:

1. de_dust2 (2,100%) 2. de_inferno (0,0%)

Hvis der så havde stået flere, skulle den skrive det tilsvarende.
Desuden skal den kun skrive to decimaltal efter kommaet.

God weekend :-)
Avatar billede wster Nybegynder
16. november 2008 - 14:20 #1
Jeg tror ikke helt jeg forstår problemområdet. Har du i forvejen en klasse som er i stand til at læse en ini-fil og skal bruge hjælp til at anvende den? Hvilken datatype har mIni? Er IRC forbindelsen også en del af problemområdet?
Smid lige en kommentar så håber jeg at vi kan hjælpe :)
Avatar billede kattendk Nybegynder
16. november 2008 - 14:57 #2
aejw.cIni mIni = new aejw.cIni("c:/temp/gather/maps.ini");

Den henviser til maps.ini.
Jeg har forbindelse til IRC osv. Det jeg skal have lavet er en stats over mapsne med hvor mange gange de er blevet spillet og i procent tal.

Håber du kan hjælpe :-)
Avatar billede wster Nybegynder
16. november 2008 - 20:35 #3
Okay, så tror jeg at jeg har fanget den!

Du har tilsyneladende anvendt aejw's INI Class til .NET fra codeproject:
http://www.codeproject.com/KB/files/aejw_ini_class.aspx

Jeg kender ikke lige til den specifikke implementation aejw har brugt og ved meget lidt om de ini-filer der outputtes til counter-strike (der er da counter-strike, er det ikke?), men jeg har forsøgt lige at sætte mig ind i, hvordan aejw's kode kan benyttes.

Her er et forslag til hvordan det kan gennemføres, jeg har forsøgt at holde det simpelt, så der er sikkert mulighed for optimering, hvis man finder det nødvendigt.

            aejw.cIni ini = new aejw.cIni(@"c:/temp/gather/maps.ini");
            //maps kommer til at indeholde navne på de maps der har stats
            Array maps = new Array[0];
            //her indlæses alle maps, grunden til de læses fra stats og ikke maps, er
            //at navnene også findes under stats og på denne måde sikres der at der kun
            //medtages de maps der findes stats til.
            ini.ReadValues("stats", ref maps);
            //dette array skal indeholde værdier tilsvarende den enkelte map-værdi.
            int[] mapvalues = new int[maps.Length];
            //denne værdi angiver hvor mange spil der er spillet i alt.
            //den er nødvendig for at kunne udregne procent.
            int totalPlays = 0;
            //her gennemgåes hvert mapnavn og der hentes en værdi for hvert map
            for (int i = 0; i < maps.Length; i++)
            {
                mapvalues[i] = Convert.ToInt32(ini.ReadValue("stats", (string)maps.GetValue(i)));
                //totalPlays inkrementeres tilsvarende den værdi som indlæses
                totalPlays += mapvalues[i];
            }
       
            //Her er anvendt en stringbuilder for at sammensætte resultat-stringen
            //man kunne også bare bruge en string og lægge til denne løbende.
            //Der anvendes en format-string for at opstille data på den ønskede måde.
            //Bemærk: procent udregnes med heltals-division, dvs. ingen decimaltal -
            //en trediedel (1/3) vil blive repræsenteret som 33% - der rundes altid ned
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < maps.Length; i++)
                builder.Append(String.Format("{0}. {1} ({2},{3}%) ", i+1, maps.GetValue(i), mapvalues[i], (mapvalues[i] * 100) / totalPlays));
            //output svarer til den ønskede resultatstring
            string output = builder.ToString();

Jeg har gået ud fra at det er aejw's implementation du har anvendt, hvis det ikke er tilfældet vil ovenstående kode ikke fungere. Hvis det er, burde 'output' blive sat lig "1. de_dust2 (2,100%) 2. de_inferno (0,0%)" givet at den beskrevne ini-fil anvendes som input.

Jeg har været lidt i tvivl om hvad du mente med "Desuden skal den kun skrive to decimaltal efter kommaet.", men jeg går ud fra at du mener at 66.66666% skal repræsenteres som 66%. Hvis det ikke er tilfældet må vi lige vende tilbage til den.

Løsningen er ikke helt fejlsikret, hvis der under [stats] tagget i ini-filen kan forekomme ugyldige data, såsom "de_dust2=kk" eller "de_dust=" (hvor værdien ikke er sat), vil programmet sandsynligvis crashe. Det kan vi dog se lidt nærmere på, hvis det bliver relevant.

Jeg håber at det gav nogenlunde mening :)
Avatar billede kattendk Nybegynder
16. november 2008 - 23:08 #4
Tak for det, men den virker desværre ikke! :(

                if (text == "!stats")
                {
                    aejw.cIni ini = new aejw.cIni(@"c:/temp/gather/maps.ini");
                    Array maps = new Array[0];
            //her indlæses alle maps, grunden til de læses fra stats og ikke maps, er
            //at navnene også findes under stats og på denne måde sikres der at der kun
            //medtages de maps der findes stats til.
            ini.ReadValues("stats", ref maps);
            //dette array skal indeholde værdier tilsvarende den enkelte map-værdi.
            int[] mapvalues = new int[maps.Length];
            //denne værdi angiver hvor mange spil der er spillet i alt.
            //den er nødvendig for at kunne udregne procent.
            int totalPlays = 0;
            //her gennemgåes hvert mapnavn og der hentes en værdi for hvert map
            for (int i = 0; i < maps.Length; i++)
            {
                mapvalues[i] = Convert.ToInt32(ini.ReadValue("stats", (string)maps.GetValue(i)));
                //totalPlays inkrementeres tilsvarende den værdi som indlæses
                totalPlays += mapvalues[i];
            }
     
            //Her er anvendt en stringbuilder for at sammensætte resultat-stringen
            //man kunne også bare bruge en string og lægge til denne løbende.
            //Der anvendes en format-string for at opstille data på den ønskede måde.
            //Bemærk: procent udregnes med heltals-division, dvs. ingen decimaltal -
            //en trediedel (1/3) vil blive repræsenteret som 33% - der rundes altid ned
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < maps.Length; i++)
                builder.Append(String.Format("{0}. {1} ({2},{3}%) ", i+1, maps.GetValue(i), mapvalues[i], (mapvalues[i] * 100) / totalPlays));
            //output svarer til den ønskede resultatstring
            string output = builder.ToString();
            cmd("PRIVMSG " + chan + " : " + output);
            }

Jeg får følgende to fejl:

1. 'aejw.cIni' does not contain a definition for 'ReadValues' and no extension method 'ReadValues' accepting a first argument of type 'aejw.cIni' could be found (are you missing a using directive or an assembly refence?)

2. No overload for method 'ReadValue' takes '2' arguments

Jeg er ret ny til c#, så håber du kan bære over med mig :) Tror du, at du kan hjælpe med det?

Ja det er til noget counter-strike :)
Som du siger med ugyldige data, som de_dust2=kk kan ikke ske. Da jeg opretter dem således, at de starter med 0 :) Så værdien er altid sat.

Forløbig tak for hjælpen :)
Avatar billede wster Nybegynder
16. november 2008 - 23:38 #5
Okay, det kan ske fordi du ikke anvender samme version af aejs's ini-læser, som den jeg har kunnet finde. Prøv at undersøge om cINI.cs i det projekt jeg har linket ( http://www.codeproject.com/KB/files/aejw_ini_class.aspx ), svarer til den fil du sidder med. Undersøg evt. om modified datoen og build nummeret beskrevet i toppen af filen er ens. Hvis de ikke er ens, kan du enten hente den anden version og anvende den eller linke til den version du bruger og så må vi se om der findes tilsvarende metoder på den.
Avatar billede kattendk Nybegynder
17. november 2008 - 07:49 #6
Jeg bruger ikke den metode, jeg bruger readini for at læse og ikke readvalues.. Hvis det er det du mener? :-)

Som sagt har jeg, aejw.cIni mIni = new aejw.cIni("c:/temp/gather/maps.ini");

Den bruger jeg så ledes; (mIni.Readini("SEKTION", DATA)) - så mIni.readnini("stats","de_dust2) = 2 :)
Avatar billede wster Nybegynder
17. november 2008 - 09:12 #7
Grunden til jeg spørger efter et link til den fil du anvender er, at det ikke er en del af standardbiblioteket og jeg kender derfor ikke til hvilke metoder der er gjort tilgængelige.

Tilsyneladende er den ene af de metoder jeg har anvendt 'ReadValue' tilsvarende din implementations Readini(string section, string data), så hvis du udskifter det sted jeg har skrevet ReadValue med Readini, burde den i hvert fald fungere.

ReadValues (BEMÆRK: med 's' på til sidst) kan ifølge din compiler ikke findes. Derfor har jeg brug for at du viser mig hvilken fil du sidder med (formodentlig kaldet cINI.cs). Hvis der ikke findes en metode tilsvarende ReadValues i din implementation, må vi bruge Readini på [maps] sectionen, men det kigger vi lige på.
Avatar billede kattendk Nybegynder
17. november 2008 - 19:16 #8
Jeg kan ikke bruge ReadValues, den kommer med fejl.

Jeg ved ikke hvad du tænker på med hensyn til hvad jeg bruger, jeg bruger bare readini :)
Avatar billede wster Nybegynder
17. november 2008 - 23:10 #9
Du kører metoder på instansen mIni, du instantialiserer den ved at skrive new aejw.cIni(@"c:/temp/gather/maps.ini"), det betyder at din implementation kender til Klassen cIni - Den klasse er ikke en del af standardbiblioteket og jeg ved derfor ikke hvad der står i lige præcis din.

I din objekt explorer kan du sandsynligvis se en fil der hedder noget i retningen af "cIni.cs", vis mig hvad der står i den eller giv mig et link til det sted du har hentet den.

Alternativt kan du downloade den version af filen, som jeg har skrevet kodestumpen udfra (jeg har linket længere oppe). Hvis du anvender den, bør programmet fungere.
Avatar billede kattendk Nybegynder
17. november 2008 - 23:30 #10
Er det den her du mener? aejw.cIni mIni = new aejw.cIni("c:/temp/gather/maps.ini");

Jeg har den ikke nogen steder fra, det er en der har fikset det :)
Avatar billede wster Nybegynder
18. november 2008 - 08:05 #11
Hvem end der har fikset det så har han hentet en version af aejw's ini læser fra et eller andet sted. Det er ikke .ini filen jeg mener, men den .cs fil, som indeholder det kode der bliver kørt når du f.eks. skriver mIni.Readini("maps", bane).

Prøv eventuelt at vælge View -> Solution Explorer og se om du ikke kan finde cIni.cs i den liste der bliver synlig. Du bør også kunne finde den hvis du søger efter den i din projektmappe, med mindre den er blevet omdøbt eller det drejer sig om en dll.
Avatar billede kattendk Nybegynder
18. november 2008 - 17:27 #12
[ cINI - INI API Legacy Class (Ascii) ]
  ---------------------------------------
  Copyright (c)2004-2007 aejw.com
  http://www.aejw.com/
 
Build:        0022 - Feb 2007

        public string Readini(string section, string key)
        {

            return getString(section.Replace("[", "¤%&&").Replace("[", "¤%&%").Replace("|", "¤%%%"), key.Replace("[", "¤%&&").Replace("[", "¤%&%").Replace("|", "¤%%%"), "").Replace("¤%&&", "[").Replace("¤%&%", "]").Replace("¤%%%", "|");
       
        }

Bare noget af det, er det noget, som du kan bruge? :)
Avatar billede wster Nybegynder
18. november 2008 - 23:34 #13
Det er det. Det build du tilsyneladende har, er det samme som det, jeg sidder med. Dog er der ikke nogen metode med navnet Readini, hvilket får mig til at tro at den fil du har, er blevet ændret.

Jeg syntes at det nemmeste ville være at du henter aejw's kode igen og får den version som indeholder alle de metoder du skal bruge.

Det kan du gøre ved at downloade hans projekt og tilføje cIni.cs filen til dit projekt ( http://www.aejw.com/default.aspx?page=dev/code/cini ), eller du kan lave en ny klasse og kopiere koden derfra ind i klassen ( http://pastebin.com/m40674849 )
Avatar billede kattendk Nybegynder
19. november 2008 - 00:24 #14
Jeg får stadig samme fejl..

Er der ikke en anden udvej end readvalues?
Avatar billede wster Nybegynder
19. november 2008 - 09:49 #15
Ikke lige jeg kan komme efter. Værdierne der ledes efter findes også under [maps] tagget, men hvis de skal læses skal man kende til navnet på variablen, som også er mapnavnet.

Det virker underligt at du ikke kan få det til at virke med den anden fil. Hvis du vil, kan du pakke projektet ned og sende det til kogledk at gmail dot com . Så vil jeg godt kigge på det og finde ud af hvad der er galt.
Avatar billede kattendk Nybegynder
19. november 2008 - 11:24 #16
Hvis jeg smider hele den nye ind, er der intet som virker. Så har kun smidt ReadValue ind, men det virker stadig ikke.

Enten må jeg opgive, ellers også findes der en anden løsning :\
Avatar billede kattendk Nybegynder
19. november 2008 - 13:27 #17
Nu får jeg følgende fejl: Error: System.NotImplementedException: The method or operation is not implemented.
Avatar billede wster Nybegynder
19. november 2008 - 16:35 #18
Smid projektet i en vedhæftet fil til mig på kogledk at gmail dot com . Så skal jeg gøre mit bedste for at finde ud af hvad der er gået galt. Det virker til applikationen ikke kan finde metoderne.
Avatar billede kattendk Nybegynder
19. november 2008 - 21:28 #19
Har du en msn mail, så kan vi lige hurtigt finde ud af noget der?
Avatar billede wster Nybegynder
19. november 2008 - 21:41 #20
disco bundstreg 25 at tdcadsl dot dk
Avatar billede kattendk Nybegynder
19. november 2008 - 22:15 #21
Ved ikke om jeg har tilføjet den rigtige, men min er denner at haderkunder dot dk
Avatar billede wster Nybegynder
20. november 2008 - 00:32 #22
Her var svaret
Avatar billede wster Nybegynder
20. november 2008 - 00:39 #23
Til de interesserede blev de sidste problemer løst ved at importere de resterende interessante metoder fra aejws ini projekt som er nævnt flere gange ( http://www.aejw.com/default.aspx?page=dev/code/cini ).

Da maps også skal sorteres blev der kodet en sorterings metode med selection sort, som ser således ud:
        private static void Sort(ref Array maps, ref int[] mapValues)
        {
            Object[] newMaps = new Object[maps.Length];
            int[] newMapValues = new int[mapValues.Length];

            bool[] marked = new bool[mapValues.Length];

            for (int i = 0; i < mapValues.Length; i++)
            {
                int currentMax = -1, index = 0;
                for (int j = 0; j < mapValues.Length; j++)
                    if (mapValues[j] > currentMax && !marked[j])
                    {
                        index = j;
                        currentMax = mapValues[j];
                    }
                newMaps[i] = maps.GetValue(index);
                newMapValues[i] = currentMax;
                marked[index] = true;
            }
            maps = newMaps;
            mapValues = newMapValues;
        }

Herefter fungerede programmet upåklageligt.
Avatar billede kattendk Nybegynder
20. november 2008 - 00:46 #24
Jeg takker mange gange! :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester