IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: C# IComparable, Algoritmus porovnávání

Aktivity
Avatar
TonySensu
Člen
Avatar
TonySensu:22.8.2016 16:20

Ahoj jsem začátečník v C# a mám za úkol vytvořit algoritmus porovnávání kódů které vypadají nějak takto:

List<Ciselnik2> kody2 = new List<Ciselnik2> {
                new Ciselnik2("13.1"),
                new Ciselnik2("13.10"),
                new Ciselnik2("13.2"),
                new Ciselnik2("13.11"),
                new Ciselnik2("ahoj")};

Výsledkem má být seřazení tohoto listu do této podoby: 13.1, 13,2, 13.10, 13.11
kody2.Sort() seřazuje špatně - 13.1, 13.10, 13.11, 13.2...
Mám implementované rozhraní IComparable ale nevím jak na to, aby to seřazovalo tak jak chci.
Postup by měl být takový:
1).pokud některá z instancí není číselník tak vyhodit vyjimku

  1. z obou instancí si vytáhnout Kód a ten rozsekat na části podle separátoru (.)
  2. postupně každou odpovídající část z obou kódů porovnat mezi sebou. Před porovnáním je nutno řetězce srovnat na stejnou délku např. pomocí PadLeft()
  3. jakmile se některé části mezi sebou nerovnají, ukončujeme porovnání
  4. pokud dojdeme sem, jedná se o dva identické kódy

výše popsaný algoritmus by měl být aplikovatelný i na nečíselné kódy, tzn. porovná i "blablabla" : "10.2"

Takže "teorii" k tomu mám jen nevím jak to v tom C# napsat :D S C# jsem začat teprve nedávno, ale nějaké základy a OOP už jsem si pročetl tady na IT networku i jinde, ale i tak jsem na tohle zatím nepřišel.

 
Odpovědět
22.8.2016 16:20
Avatar
Neaktivní uživatel:22.8.2016 17:40

Jestli máš implementované rozhraní IComparable, tak sem postni tvojí verzi metody Compare (tzn. cos zatím zkoušel). Podíváme se na to.

Nahoru Odpovědět
22.8.2016 17:40
Neaktivní uživatelský účet
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:22.8.2016 19:14

Taky by mně zajímala ta třída "Ciselnik2"

 
Nahoru Odpovědět
22.8.2016 19:14
Avatar
TonySensu
Člen
Avatar
Odpovídá na ostrozan
TonySensu:23.8.2016 8:06
class Ciselnik2 : IComparable
   {
       public string Kod { get; set; }
       public int DalsiAtribut { get; set; }
       static Random rand = new Random();
       public Ciselnik2(string kod)
       {
           this.Kod = kod;
           DalsiAtribut = rand.Next(10,20);
       }
       public int CompareTo(object obj)
       {
           if (obj == null) return 1;

           Ciselnik2 otherCiselnik = obj as Ciselnik2;
           if (otherCiselnik != null)
           {
               /*
               string[] s = this.Kod.Split('.');
               string[] sOther = otherCiselnik.Kod.Split('.');


                   s[i].PadLeft(2, '0');
                   sOther[i].PadLeft(2, '0');
             */


               return this.Kod.CompareTo(otherCiselnik.Kod);
           }
           else
               throw new ArgumentException("Object is not Ciselnik2");
       }

   }

Ta třída je jen pro zkušební účely..až to bude fungovat tak to pak aplikuji na projekt do třídy, která má další vlastnosti atd.. ale to už by snad nemělo vadit.

 
Nahoru Odpovědět
23.8.2016 8:06
Avatar
TonySensu
Člen
Avatar
Odpovídá na Neaktivní uživatel
TonySensu:23.8.2016 8:09
public int CompareTo(object obj)
     {
         if (obj == null) return 1;

         Ciselnik2 otherCiselnik = obj as Ciselnik2;
         if (otherCiselnik != null)
         {
             /*
             string[] s = this.Kod.Split('.');
             string[] sOther = otherCiselnik.Kod.Split('.');


                 s[i].PadLeft(2, '0');
                 sOther[i].PadLeft(2, '0');
           */


             return this.Kod.CompareTo(otherCiselnik.Kod);
         }
         else
             throw new ArgumentException("Object is not Ciselnik2");
     }

V podstatě je to jen něco, co jsem našel v oficialni dokumentaci od MS (kterou nesnašim :D) a nějaky pokus, který jsem zakomentoval - netuším, jak to tam správně zakomponovat.

Editováno 23.8.2016 8:10
 
Nahoru Odpovědět
23.8.2016 8:09
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na TonySensu
ostrozan:23.8.2016 8:31

A je nutný ten formát"13.1 , 13.10 ......" nebylo by lepší něco co půjde líp seřadit "1301,1310......" než vymýšlet nějaké krkolomnosti?
Ta třída mně zajímala kvůli tomu, jestli umí i něco jiného, než uchovat nějaký kód. Takhle se zdá zbytečná a vystačíš si s kolekcí stringů

 
Nahoru Odpovědět
23.8.2016 8:31
Avatar
TonySensu
Člen
Avatar
Odpovídá na ostrozan
TonySensu:23.8.2016 8:33

Bohužel formát je potřeba takový je to nějaký kód...Jasný takto na test by stačila kolekce stringů, ale potom v druhém projektu to chci aplikovat na třídu, která umí i další věci.

 
Nahoru Odpovědět
23.8.2016 8:33
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:23.8.2016 9:31

Tak si to do toho formátu uprav - stejně ses tou cestou vydal, ale já bych to dal už do té property

private string code;
public string Kod {
    get { return code; }
    set
    {
        string s = value;
        string[] s2 = s.Split('.');
        code = s2[0].PadLeft(2, '0') + s2[1].PadLeft(2, '0');

    }

}

a analogicky i do konstruktoru

Editováno 23.8.2016 9:32
 
Nahoru Odpovědět
23.8.2016 9:31
Avatar
TonySensu
Člen
Avatar
Odpovídá na ostrozan
TonySensu:23.8.2016 9:49

Ve výsledku žádný rozdíl. Jak to myslíš v tom konstruktoru?

 
Nahoru Odpovědět
23.8.2016 9:49
Avatar
TonySensu
Člen
Avatar
Odpovídá na ostrozan
TonySensu:23.8.2016 10:01

Takhle jsi to sice přeformátoval už při nastavení té property, ale stejně při porovnávání to porovnává celý řetězec, takže asi kvůli tomu si myslím je ten výsledek stejný. Ono by to asi chtělo nějak udělat aby to porovnávalo každej part toho kódu zvlášt s druhým kódem a jeho částí, která odpovída té části u prvního kódu.

 
Nahoru Odpovědět
23.8.2016 10:01
Avatar
TonySensu
Člen
Avatar
TonySensu:23.8.2016 10:05

Navíc ve výstupu chci, aby kody vypadali stejně, tzn: 13.1 a ne 13.01.

 
Nahoru Odpovědět
23.8.2016 10:05
Avatar
TonySensu
Člen
Avatar
Odpovídá na ostrozan
TonySensu:23.8.2016 10:35

Tak už se mi to podařilo částečně rozjet, ale vyhodí to exception, když tam přidám třeba to "ahoj" asi kvůli tomu

(s[0].PadLeft(2, '0')) + (s[1].PadLeft(2, '0'))

Tady se počítá s tím, že ten kód bude mít vždycky 2 části..nejde to nějak upravit, aby to bylo univerzální? Aby to porovnalo "ahoj", ale i třeba 13.10.5 atd..

 
Nahoru Odpovědět
23.8.2016 10:35
Avatar
TonySensu
Člen
Avatar
TonySensu:23.8.2016 10:39

Napadlo mě, že bych si mohl zjistit délku pole toho stringu a pak udělat for cyklus na ten PadLeft

 
Nahoru Odpovědět
23.8.2016 10:39
Avatar
TonySensu
Člen
Avatar
TonySensu:23.8.2016 11:15
public int CompareTo(object obj)
      {
          if (obj == null) return 1;

          Ciselnik2 otherCiselnik = obj as Ciselnik2;
          if (otherCiselnik != null)
          {
              string[] s = this.Kod.Split('.');
              string[] sOther = otherCiselnik.Kod.Split('.');

              int str1Len = s.Length;
              int str2Len = sOther.Length;

              if (str1Len < str2Len)
              {
                  //vytvořit novou instanci pole velikostne srovnanou se sOther
              }
              else if (str1Len > str2Len)
              {
                  //vytvořit novou instanci pole velikostne srovnanou se s
              }
              else
              {
                  //nemusim resit pole jsou stejne velky
              }

              //for cyklus, srovnat pocet znaku v jendotlivych polozkach pole
              string str1 = "";
              string str2 = "";
              for (int i = 0; i < str1Len; i++)
              {
                str1 += str1 + (s[i].PadLeft(2, '0'));
              }
              for (int i = 0; i < str2Len; i++)
              {
                  str2 += (sOther[0].PadLeft(2, '0'));
              }


              return str1.CompareTo(str2);
          }
          else
              throw new ArgumentException("Object is not Ciselnik2");
      }

Tak momentálně to mám takhle, ale stále to nefunguje podle představ a nevím jak to udělat..Ten for cyklus mám špatně, protože to lepím zase zpátky do jednoho stringu, mělo by to fungovat, tak že to bude porovnávat jednotlivé položky pole s druhým polem a když v nějaké části najde rozdíl tak se hned porovnávání ukončuje - tam kde byla nalezena menší hodnota je automaticky celý kod menší. Před tím - v těch Ifech je ještě potřeba srovnat délky obou polí - menší vyplnit nulovými hodnotami...Kdyby někdo věděl jak to zprovoznit tak budu velice rád :D

 
Nahoru Odpovědět
23.8.2016 11:15
Avatar
Neaktivní uživatel:23.8.2016 11:52

Podle mě sis to zkomplikoval tím, že kód ukládáš jako string, a pak čekáš, že pokud to bude číselný kód, aby to řadil a porovnával jako čísla, a pokud je kód nějaké slovo (písmenka), tak aby to porovnával jako string. Metoda Sort (úplně první příspěvek) ti pole seřadila dobře, podle abecedy. Nechceš spíš překopat ten návrh? Když přemýšlím nad řešením stávajícího, tak mě napadají jenom error-prone bullshity :-D Jaký je vlastně účel tohoto porovnávání? Je to učebnicový příklad, nebo to má vyšší smysl?

Nahoru Odpovědět
23.8.2016 11:52
Neaktivní uživatelský účet
Avatar
TonySensu
Člen
Avatar
Odpovídá na Neaktivní uživatel
TonySensu:23.8.2016 12:03

Bohužel kdyby to byla čísla tak 13.10 a 13.1 bude to stejné. A ty kódy musí být prostě string no mám to tak zadaný. Účel proč se to musí řadit takhle ani nevím mám to v zadání :D

 
Nahoru Odpovědět
23.8.2016 12:03
Avatar
TonySensu
Člen
Avatar
Odpovídá na Neaktivní uživatel
TonySensu:23.8.2016 12:08

9.4
13.1
13.2
13.11
13.21
13.10
13.5.11
13.5.10
15.17
Ahoj

Momentálně to ty čísla seřazuje takhle, což je skoro dobře až na to, že 13.10 by mělo být před 13.11 a 13 .21 za 13.11 atd ..víš jak :D

 
Nahoru Odpovědět
23.8.2016 12:08
Avatar
Odpovídá na TonySensu
Neaktivní uživatel:23.8.2016 12:29

Nemyslel jsem jako desetinná čísla, ale že každá část se přeparsuje na Integer a ty se porovnají - 13.1 a 13.10 znamená porovnat 13 vs. 13 (stejné) a pak 01 vs. 10 (01 je menší), takže pokud to chápu, seřadí to správně: 13.1 a potom 13.10. Ještě ale nechápu, v posledním příspěvku máš že např. 13.5 je až za 13.11. Pokud však porovnáváš druhou část (tzn. "5" a "11"), tak to srovnáváš na stejnou délku pomocí PadLeft, tzn. porovnává se "05" vs. "11", a "05" je přeci menší než 11. Nemělo by to být přehozené, podle zadání?

Nahoru Odpovědět
23.8.2016 12:29
Neaktivní uživatelský účet
Avatar
TonySensu
Člen
Avatar
Odpovídá na Neaktivní uživatel
TonySensu:23.8.2016 12:45

Jo takhle mmm to by asi bylo fungovalo no, ale nevím co by to udělalo s tím "ahoj" :D to už by asi nebylo dobré :D jinak to když to má víc jak 2 části tak to jsi mě teď zmátl :D jako když se na to podívám tak bych souhlasil stebou. To budu muset ještě zjistit jak si to představujou :D

 
Nahoru Odpovědět
23.8.2016 12:45
Avatar
Odpovídá na TonySensu
Neaktivní uživatel:23.8.2016 12:56

Zmátl jsem i sám sebe. Nevím vlastně, jestli se porovnává "zleva" nebo "zprava". Tj. při porovnávání kódu s jiným počtem částí např. "13.5.10" a "13.11". Porovná se "13" vs. "13" a pak "5" vs. "11", ANEBO "10" vs. "11" a pak "5" vs. "13" ? Jinak na jakou školu chodíš (jen tak ze zvědavosti).

Nahoru Odpovědět
23.8.2016 12:56
Neaktivní uživatelský účet
Avatar
TonySensu
Člen
Avatar
Odpovídá na Neaktivní uživatel
TonySensu:23.8.2016 13:04

Určitě by to mělo být zleva :D Já už na školu nechodím letos jsem odmaturoval pak jsem si dal měsíc prázdnin a od července hurá do práce :D :D Jelikož jsem se na střední o C# neslyšel ani slovo a místo toho jsme se učili Visual Basic 6 v podstatě celý 4 roky ( -_- ), tak se všechno učím přímo při práci no :D Jinak ve volným čase jsem vždycky něco patlal v Game Makeru to mě bavilo i díky tomu jsem na tom o něco líp, než kdybych se učil jenom to co jsme dělali ve škole

 
Nahoru Odpovědět
23.8.2016 13:04
Avatar
TonySensu
Člen
Avatar
TonySensu:23.8.2016 13:05

Přemýšlím, že brzo nahradím Game Maker za Unity, když už začínám s tím C# :D

 
Nahoru Odpovědět
23.8.2016 13:05
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na TonySensu
ostrozan:23.8.2016 23:20

co se týká toho "ahoj" - ty bys vůbec neměl dopustit, aby se ti instance třídy s nesmyslem vůbec vytvořila - nejlíp to ošetřit hned na vstupu - ovšem co je tím vstupem - jestli ten kód někdo zadává přes klávesnici, nebo je v nějakém souboru, nebo příjde po nějaké lince z venku - tos nám zatím neprozradil

ale minimálně by ten string , než ho dáš do kostruktoru měl projít aspoň něčím takovým:

foreach (char c in Kod)
{
    if(!Char.IsNumber(c)&&c!='.')
    {
        //neco proved
    }
 }

teda budeš mít jistotu, že string obsahuje pouze číslice a tečky
i když to nevyfiltruje nesmysly typu "..123" , nebo ".........."

 
Nahoru Odpovědět
23.8.2016 23:20
Avatar
TonySensu
Člen
Avatar
Odpovídá na ostrozan
TonySensu:24.8.2016 9:08

Jak se tam dostane ten vstup to nevím, ale požadavek je, aby to i tenhle nesmysl dokázalo porovnat.

 
Nahoru Odpovědět
24.8.2016 9:08
Avatar
TonySensu
Člen
Avatar
TonySensu:24.8.2016 9:11
class Ciselnik2 : IComparable
   {
       public string Kod { get; set; }
       public int DalsiAtribut { get; set; }
       static Random rand = new Random();
       public Ciselnik2(string kod)
       {
           this.Kod = kod;
           DalsiAtribut = rand.Next(10, 20);
       }
       public int CompareTo(object obj)
       {
           if (obj == null) return 1;

           Ciselnik2 otherCiselnik = obj as Ciselnik2;
           if (otherCiselnik != null)
           {
               string[] s = this.Kod.Split('.');
               string[] sOther = otherCiselnik.Kod.Split('.');

               int str1Len = s.Length;
               int str2Len = sOther.Length;

               var sList = s.ToList();
               var s2List = sOther.ToList();

               if (str1Len < str2Len)
               {

                   //string[] newS = new string[];

                   for (int i = 0; i < (str2Len - str1Len); i++)
                   {
                       sList.Add("0");
                   }

               }
               else if (str1Len > str2Len)
               {


                   for (int i = 0; i < (str1Len - str2Len); i++)
                   {
                       s2List.Add("0");
                   }
               }
               else
               {
                   //nemusim resit pole jsou stejne velky
               }



               //for cyklus, srovnat pocet znaku v jendotlivych polozkach pole
               for (int i = 0; i < sList.Count; i++)
               {
                   if (sList[i].Length > s2List[i].Length) {
                       sList[i].PadLeft(sList[i].Length, '0');
                       s2List[i].PadLeft(sList[i].Length, '0');
                   }
                   else if (sList[i].Length < s2List[i].Length)
                   {
                       sList[i].PadLeft(s2List[i].Length, '0');
                       s2List[i].PadLeft(s2List[i].Length, '0');
                   }
               }

               int porovnej = 666;
               for (int i = 0; i < sList.Count; i++)
               {
                   porovnej = sList[i].CompareTo(s2List[i]);
                   if (porovnej < 0 || porovnej > 0)
                   {
                       return porovnej;
                       //break - zjistil ze polozka pole je mensi nebo vetsi
                   }
               }
               //jinak dojde az nakonec a vrati vysledek
               return porovnej;
           }
           else
               throw new ArgumentException("Object is not Ciselnik2");
       }

Teď jsem to zkusil takhle upravit, ale nefunguje to :D :(

Výsledek: 13.1
13.10
13.11
13.2
13.21
13.5.10
13.5.11
15.17
9.4
Ahoj

Editováno 24.8.2016 9:13
 
Nahoru Odpovědět
24.8.2016 9:11
Avatar
DZetko
Člen
Avatar
DZetko:24.8.2016 15:20

Je součástí zadání implementovat IComparable a List<>.Sort()?

 
Nahoru Odpovědět
24.8.2016 15:20
Avatar
TonySensu
Člen
Avatar
 
Nahoru Odpovědět
24.8.2016 15:23
Avatar
Ondřej Štorc
Tvůrce
Avatar
Odpovídá na TonySensu
Ondřej Štorc:24.8.2016 15:49

Nezkoušel jsem to ale měl by to takhle fungovat. Kdyby jsi měl dotazy k kódu, případně námitky že se dá něco udělat lépe (určitě dá) tak se ozvi:

public int CompareTo(object obj)
{
    if (obj == null) return 1;
    if (!(obj is Ciselnik2)) throw new ArgumentException();

    Ciselnik2 ciselnik = obj as Ciselnik2;

    Regex regex = new Regex("[0-9]+[.][0-9]+");
    // Ale měl by jsi to už ověřovat při vzniku...
    if (!regex.IsMatch(this.Kod) && regex.IsMatch(ciselnik.Kod)) return -1;
    if (!regex.IsMatch(ciselnik.Kod) && regex.IsMatch(this.Kod)) return 1;

    if (this.Kod == ciselnik.Kod) return 0;

    var thisKod = Kod.Split('.');
    var objKod = ciselnik.Kod.Split('.');

    if (thisKod[0] == objKod[0])
    {
        return int.Parse(thisKod[1]).CompareTo(int.Parse(objKod[1]));
    }
    return int.Parse(thisKod[0]).CompareTo(int.Parse(objKod[0]));

}
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
24.8.2016 15:49
Život je příliš krátký na to, abychom bezpečně odebírali USB z počítače..
Avatar
TonySensu
Člen
Avatar
Odpovídá na Ondřej Štorc
TonySensu:24.8.2016 15:54

Seš borec - funguje to :D Moc díky :)

 
Nahoru Odpovědět
24.8.2016 15:54
Avatar
TonySensu
Člen
Avatar
Odpovídá na Ondřej Štorc
TonySensu:25.8.2016 8:13

Jen teda vidím, že to funguje jen na kody, který maj dvě časti - 13.10, 13.1...potřebuju, aby to šlo na jakkoliv dlouhej kod např. 13.5.10. Zkusím to sám upravit, kdyby se mi to nepodařilo tak se ozvu :D

 
Nahoru Odpovědět
25.8.2016 8:13
Avatar
TonySensu
Člen
Avatar
Odpovídá na Ondřej Štorc
TonySensu:25.8.2016 8:32
public int CompareTo(object obj)
      {
          if (obj == null) return 1;
          if (!(obj is Ciselnik2)) throw new ArgumentException();

          Ciselnik2 ciselnik = obj as Ciselnik2;

          Regex regex = new Regex("[0-9]+[.][0-9]+");

          if (!regex.IsMatch(this.Kod) && regex.IsMatch(ciselnik.Kod)) return -1;
          if (!regex.IsMatch(ciselnik.Kod) && regex.IsMatch(this.Kod)) return 1;

          if (this.Kod == ciselnik.Kod) return 0;

          var thisKod = Kod.Split('.');
          var objKod = ciselnik.Kod.Split('.');

          int str1Len = thisKod.Length;
          int str2Len = objKod.Length;

          var sList = thisKod.ToList();
          var s2List = objKod.ToList();

          if (str1Len < str2Len)
          {



              for (int i = 0; i < (str2Len - str1Len); i++)
              {
                  sList.Add("0");
              }

          }
          else if (str1Len > str2Len)
          {


              for (int i = 0; i < (str1Len - str2Len); i++)
              {
                  s2List.Add("0");
              }
          }

          int porovnej = 666;
          for (int i = 0; i < s2List.Count; i++)
          {
              porovnej = int.Parse(sList[i]).CompareTo(int.Parse(s2List[i]));
              if (porovnej < 0 || porovnej > 0)
              {
                  return porovnej;

              }
          }

          return porovnej;

      }

Už funguje jak má :)

 
Nahoru Odpovědět
25.8.2016 8:32
Avatar
TonySensu
Člen
Avatar
TonySensu:25.8.2016 15:59

Tak jsme nakonec zjistili, že moje verze byla správně, ale jen chybělo uložení po provedeni PadLeft jelikož to pouze vrací ale nenastavuje. Takže jen taková miniaturní úprava a tenhle kod funguje suprově. Jsem rád, že to tu konečně můžu uzavřít :D

public int CompareTo(object obj)
      {
          if (obj == null) throw new ArgumentNullException(nameof(obj));

          Specifikace otherSpecifikace = obj as Specifikace;

          if (otherSpecifikace == null)
              throw new ArgumentException("Object is not Specifikace");


          string[] thisArrayKod = this.Kod.Split('.');
          string[] otherArrayKod = otherSpecifikace.Kod.Split('.');

          int thisKodArrayLen = thisArrayKod.Length;
          int otherKodArrayLen = otherArrayKod.Length;

          var thisListKod = thisArrayKod.ToList();
          var otherListKod = otherArrayKod.ToList();

          if (thisKodArrayLen < otherKodArrayLen)
          {

              for (int i = 0; i < (otherKodArrayLen - thisKodArrayLen); i++)
              {
                  thisListKod.Add("0");
              }

          }
          else if (thisKodArrayLen > otherKodArrayLen)
          {

              for (int i = 0; i < (thisKodArrayLen - otherKodArrayLen); i++)
              {
                  otherListKod.Add("0");
              }
          }

          for (int i = 0; i < thisListKod.Count; i++)
          {

              if (thisListKod[i].Length > otherListKod[i].Length)
              {

                  otherListKod[i] = otherListKod[i].PadLeft(thisListKod[i].Length, '0');
              }
              else if (thisListKod[i].Length < otherListKod[i].Length)
              {
                  thisListKod[i] = thisListKod[i].PadLeft(otherListKod[i].Length, '0');

              }
          }

          int compareResult = 0;
          for (int i = 0; i < thisListKod.Count; i++)
          {
              compareResult = thisListKod[i].CompareTo(otherListKod[i]);
              if (compareResult != 0)
              {
                  return compareResult;

              }
          }

          return 0;
      }

btw názvy už jsem změnil, aby mi to sedělo do real projektu.

Editováno 25.8.2016 16:00
 
Nahoru Odpovědět
25.8.2016 15:59
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 32 zpráv z 32.