[C#]Na podstawie średnicy D3 dobierz śrubę trapezową z tablicy array

0

Witam,
jestem początkujący w C#. Chcę napisać prosty program, który na podstawie wyniku obliczenia średnicy wewnętrznej śruby trapezowej dobierze śrubę z katalogu śrub.
Program wylicza średnicę D3, przykładowo wynik to 7.09mm (wynikd3).

            Console.WriteLine("Podaj wartość udźwigu:");
            string userResponse = Console.ReadLine();
            ///Parsowanie
            _ = int.TryParse(userResponse, out int mUdzwig);

            Console.WriteLine("Podaj wartość wzniosu:");
            string userResponse1 = Console.ReadLine();
            _ = int.TryParse(userResponse1, out _);

            /////1.1 Obliczenia śruby
            /////1.1.1 Obliczenie średnicy śruby
            Console.WriteLine("podaj wartość kcj:");
            string userResponse2 = Console.ReadLine();
            _ = int.TryParse(userResponse2, out int mkcj);
            float mwspolczynnik = 1.3f;
            float mwspolczynnik2 = 1.13f;
            int mqz = (int)(mwspolczynnik * mUdzwig);
            float d3 = (float)(mwspolczynnik2 * Math.Sqrt(mqz / mkcj));
            float wynikd3 = (float)Math.Round(d3, 2);
            Console.WriteLine(wynikd3);

następnie stworzyłem tablicę z przykładowymi śrubami ze strony producenta:

            /////Określenie śruby trapezowej
            float[] SrubyKatalog = new float[3];
            SrubyKatalog[0] = 5.84f;
            SrubyKatalog[1] = 7.84f;
            SrubyKatalog[2] = 9.84f;

Chcę żeby konsola podała pierwszy wynik z tablicy SrubyKatalog, który będzie większy od wyniku (wynikd3). Przykładowo wynikd3 = 7.09 a program ma podać śrubę z katalogu SrubyKatalog[1] = 7.84f . Nie wiem kompletnie jak to ugryźć. Próbowałem pętli while, for ale nie wiem czy idę w dobrą stronę.

2

Najprościej chyba będzie używając LINQ:

float output = SrubyKatalog.Where(val => input < val)
    .First();

Metoda zwróci kolekcję z wartościami spełniającymi warunek i poda jej pierwszy element, czyli ten, który Cię interesuje.

3

Jeśli masz uporządkowane elementy w tablicy to chyba wystarczy coś takiego:

float wynikd3 = 7.09;
float[] SrubyKatalog = new float[3];
            SrubyKatalog[0] = 5.84f;
            SrubyKatalog[1] = 7.84f;
            SrubyKatalog[2] = 9.84f;
foreach (float sruba in SrubyKatalog)
        {
            if (sruba >= wynikd3){
               Console.WriteLine(sruba);
               return 1;
            }
        }

Pisane z palca, bez testu i bardzo dawno już nic nie napisałem w C#, ale zapinanie do tego LINQa to lekka przesada.

0
 foreach (float sruba in SrubyKatalog)
       {
           if (sruba >= wynikd3){
             Console.WriteLine(sruba);
             return 1;
           }
       }

return 1 nie działa, wywala błedy. Jak skasuje return 1; to wyświetla śruby większe niż wynikd3.

Since 'Program.Main(string[])' returns void, a return keyword must not be followed by an object expression

2

Zobacz czy zadziała samo return.
Return ma przerwać pęlę, ale wynik zależy od tego co masz ustawione jako wartość zwracana z funkcji. Nie widzę deklaracji funkcji więc nie powiem.

0

Samo return działa. Dzięki

2

Jak działa to działa. Dobrą praktyką jest wydzielanie jak najmniejszych części kodu do nowych funkcji. No i return to przerwanie pętli ale i funkcji więc typ zwracany musi się zgadzać z tym co zadeklarujesz. Jak masz deklarację, że funcja nie zwraca "niczego" (void) to jak zwracała int 1 był błąd.

0

Zamiast return dałem break. Wtedy działa jak należy. Dzięki za pomoc.
Zmieniłem trochę kod zamiast tablicy dałem listę bo chciałem żeby wyświetlało też string NazwaSruby.

            var sruba1 = new SrubyKatalog();
            sruba1.SrednicaD3 = 5.84f;
            sruba1.NazwaSruby = "TR 10x3";
            var sruba2 = new SrubyKatalog();
            sruba2.SrednicaD3 = 7.84f;
            sruba2.NazwaSruby = "TR 12x3";
            var sruba3 = new SrubyKatalog();
            sruba3.SrednicaD3 = 9.84f;
            sruba3.NazwaSruby = "TR 14x3";

            List<SrubyKatalog> sruby = new List<SrubyKatalog>(3);
            sruby.Add(sruba1);
            sruby.Add(sruba2);
            sruby.Add(sruba3);

            foreach(SrubyKatalog srubki in sruby)
            {
                if(srubki.SrednicaD3 >= wynikd3)
                {
                    Console.WriteLine($"Średnica D3: {srubki.SrednicaD3}  {srubki.NazwaSruby}");
                        break;
                }
            }
0

Witam ponownie. Cały czas staram się udoskonalać kod i dodawać nowe rzeczy do mini projektu.
Zmodyfikowałem kod i mam problem. Chcę wyświetlić gamma z private static float Warunek w Main i totalnie utknąłem w temacie. W metodzie DobranaSruba dobieram srubę, z automatu dobiera mi podziałkę z listy SrubyTrapezoweLista, Podziałkę wrzucam do private static float Warunek i teraz chcę wyświetlić to w Main. Dla was to pewnie nie jest problem dla mnie w tym momencie tak.

using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using PodnosnikLibrary;
namespace Podnosnik
{
    class PodnosnikUI
    {
        private static void SredniceD2D3(out float D2, out float D3)
        {
            var parametry = new ParametryWejsciowe();
            D2 = (float)Math.Round(Math.Sqrt(parametry.ParametrUdzwig / (Math.PI * parametry.WsWysGwintu * parametry.WsWysNakretki * parametry.Kd)), 2);
            D3 = (float)Math.Round(Math.Sqrt((4 * parametry.Beta * parametry.ParametrUdzwig) / (Math.PI * parametry.Kc)), 2);
            Console.WriteLine($"Średnica d2 = {D2}");
            Console.WriteLine($"Średnica d3 = {D3}");
        }
        private static void DobranaSruba(float D2, float D3)
        {
            //float podzialka;
            foreach (SrubyTrapezoweProperties sruba in SrubyTrapezoweLista.sruby)
            {
                if(sruba.SrednicaD2 > D2 && sruba.SrednicaD3 > D3)
                {
                    Console.WriteLine($"Dobrano śrubę trapezową: {sruba.OznaczenieSruby}");
                    float podzialka = sruba.Podzialka;
                    Console.WriteLine($"Podziałka śruby {podzialka}");
                    break;
                }
            }
        }
        private static void WarSamohamownosci()
        {
            List<WarSamoHProperties> gwintData = ParametryGwint.GwintData();
            foreach (var warS in gwintData)
            {
                if (warS.IDg == 1)
                //1 = "Trapezowy niesymetryczny";
                //2 = "Trapezowy symetryczny";
                //3 = "Prostokątny";
                //4 = "Metryczny";
                {
                    Console.WriteLine($"Zarys gwintu: {warS.ZarysGwintu} | Kąt pochylenia gwintu {warS.KatPochGwi}");
                }
            }
        }
            private static void WarSamohamownosci2()
            {
                List<WarSamoHProperties> kdfData = ParametryGwint.KdfData();
                foreach (var warK in kdfData)
                {
                //1 = "Stal hartowana brąz";
                //2 = "Stal niehartowana brąz";
                //3 = "Stal hartowana żeliwo";
                //4 = "Stal niehartowana żeliwo";
                //5 = "Stal hartowana stal";
                if (warK.IDk == 1)
                    {
                        Console.WriteLine($"Materiał śruby: {warK.MatSN} | Współczynnik Kd: {warK.WspKd} | Współczynnik f: {warK.WspF}");
                    }
                }
            }
        private static float Warunek(float D2, float podzialka )
        {
            float gamma;
            gamma = (float)Math.Atan(podzialka / Math.PI * D2);
            Console.WriteLine($"Gamma = {gamma}");
            return gamma;

        }
        static void Main(string[] args)
        {
            ParametryWejsciowe.ZadaneParametry();
            SrubyTrapezoweLista.ListaSrubTrapezowych();
            float D2, D3;
            SredniceD2D3(out D2, out D3);
            DobranaSruba(D2, D3);
            WarSamohamownosci();
            WarSamohamownosci2();
            Console.ReadKey();
        }
    }
}
1

jakos mi sie nie wydaje zebys to sam pisal, ale

w main wystarczy

Console.Writeline(Warunek(D2, 5).ToString());
0

Podziałkę chcę implementować z klasy którą zrobiłem i z tej metody:

        private static void DobranaSruba(float D2, float D3)
        {
            //float podzialka;
            foreach (SrubyTrapezoweProperties sruba in SrubyTrapezoweLista.sruby)
            {
                if(sruba.SrednicaD2 > D2 && sruba.SrednicaD3 > D3)
                {
                    Console.WriteLine($"Dobrano śrubę trapezową: {sruba.OznaczenieSruby}");
                    float podzialka = sruba.Podzialka;
                    Console.WriteLine($"Podziałka śruby {podzialka}");
                    break;
                }
            }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PodnosnikLibrary
{
    public class SrubyTrapezoweLista
    {
        public static List<SrubyTrapezoweProperties> sruby = new List<SrubyTrapezoweProperties>();
        public static void ListaSrubTrapezowych()
        {
            sruby.Add(new SrubyTrapezoweProperties { OznaczenieSruby = "TR 8x1,5", SrednicaD2 = 7.25f, SrednicaD3 = 6.2f, Podzialka = 1.5f });
            sruby.Add(new SrubyTrapezoweProperties { OznaczenieSruby = "TR 10x1,5", SrednicaD2 = 9.25f, SrednicaD3 = 8.2f, Podzialka = 1.5f });
            sruby.Add(new SrubyTrapezoweProperties { OznaczenieSruby = "TR 12x2", SrednicaD2 = 11, SrednicaD3 = 8.2f, Podzialka = 2 });
            sruby.Add(new SrubyTrapezoweProperties { OznaczenieSruby = "TR 16x2", SrednicaD2 = 15, SrednicaD3 = 13.5f, Podzialka = 2 });
            sruby.Add(new SrubyTrapezoweProperties { OznaczenieSruby = "TR 20x2", SrednicaD2 = 19, SrednicaD3 = 17.5f, Podzialka = 2 });
            sruby.Add(new SrubyTrapezoweProperties { OznaczenieSruby = "TR 24x3", SrednicaD2 = 22.5f, SrednicaD3 = 20.5f, Podzialka = 3 });

            foreach (var sruba in SrubyTrapezoweLista.sruby)
            {
                Console.WriteLine($"Śruba | {sruba.OznaczenieSruby,-9} | Średnica d2 = {sruba.SrednicaD2,-9} | Średnica d3 = {sruba.SrednicaD3,-9}|");
            }
        }
    }
}
1

"SrubyTrapezoweProperties" ? Nie mieszaj języków, niedługo Hiszpański tam sie jeszcze znajdzie :)
Jak nazywasz obiekt "śruba" to nie nazywaj go "SrubyKatalog", ponieważ katalog zwykle jest zbiorem, a Ty wskazujesz na jedną śrubę, więc te klasy tak nazwij. jak po roku rozbudowy programu dojdą uszczelki, nakrętki itp. to chyba nie przypiszesz nakrętki do katalogu tylko do śruby prawda? Znam to z doświadczenia bo sam tak kiedyś robiłem. Na koniec się pogubisz i jedyne co przyjdzie to pisać wszystko od nowa

0

Coś ty mi tu popisał ;))) Jak napisałem na początku jestem początkujący(C# jakieś 3 tygodnie).Jestem inż. konstruktorem na nie inż inf. Jeszcze nie doszedłem do linq, ani nie przerabiałem dziedziczenia itp. Dopiero to zamierzam zrobić. Ale dzięki przejrzę w miarę nauki.
Generalnie to chyba wziąłeś kod z pierwszego postu bo już go w miarę nauki trochę zmieniłem. Ten projekt jest dla mnie projektem szkoleniowym a nie komercyjnym. Po angielsku wszystkich nazw nie piszę bo mi się nie chce.
Chcę w przyszłości pisać rozszerzenia do programów CAD albo programy na własne potrzeby.

Aktualny kod(reszta kodu w klasach i bibliotece.

using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using PodnosnikLibrary;
namespace Podnosnik
{
    class PodnosnikUI
    {
        private static void PodstawoweParametry(out float D2, out float D3, out float podzialka, out float gamma, out int udzwig)
        {
            udzwig = 0;
            var parametry = new ParametryWejsciowe();
            D2 = (float)Math.Round(Math.Sqrt(parametry.ParametrUdzwig / (Math.PI * parametry.WsWysGwintu * parametry.WsWysNakretki * parametry.Kd)), 2);
            D3 = (float)Math.Round(Math.Sqrt((4 * parametry.Beta * parametry.ParametrUdzwig) / (Math.PI * parametry.Kc)), 2);
            udzwig = parametry.ParametrUdzwig;
            Console.WriteLine($"Średnica d2 = {D2}");
            Console.WriteLine($"Średnica d3 = {D3}");
            podzialka = 0;
            gamma = 0;
            foreach (SrubyTrapezoweProperties sruba in SrubyTrapezoweLista.sruby)
            {
                if (sruba.SrednicaD2 > D2 & sruba.SrednicaD3 > D3)
                {
                    Console.WriteLine($"Dobrano śrubę trapezową: {sruba.OznaczenieSruby}");
                    podzialka = (float)sruba.Podzialka;
                    Console.WriteLine($"Podziałka śruby {podzialka}");
                    gamma = (float)Math.Round(Math.Atan(podzialka / Math.PI * D2),2);
                    Console.WriteLine($"Gamma = {gamma}");
                    break;
                }
            }
        }
        private static void Ro(out float KatPochGwi, out float WspF, out float ro)
        {
            KatPochGwi = 0;
            WspF = 0;
            List<WarSamoHProperties> gwintData = ParametryGwint.GwintData();
            foreach (var warS in gwintData)
            {
                if (warS.IDg == 2)
                //1 = "Trapezowy niesymetryczny";
                //2 = "Trapezowy symetryczny";
                //3 = "Prostokątny";
                //4 = "Metryczny";
                {
                    Console.WriteLine($"Zarys gwintu: {warS.ZarysGwintu} | Kąt pochylenia gwintu {warS.KatPochGwi}");
                    KatPochGwi = warS.KatPochGwi;
                }
            }
            List<WarSamoHProperties> kdfData = ParametryGwint.KdfData();
            foreach (var warK in kdfData)
            {
                //1 = "Stal hartowana brąz";
                //2 = "Stal niehartowana brąz";
                //3 = "Stal hartowana żeliwo";
                //4 = "Stal niehartowana żeliwo";
                //5 = "Stal hartowana stal";
                if (warK.IDk == 5)
                {
                    Console.WriteLine($"Materiał śruby: {warK.MatSN} | Współczynnik Kd: {warK.WspKd} | Współczynnik f: {warK.WspF}");
                    WspF = warK.WspF;
                }
            }
            double CosKPG = Math.PI * WspF / 180;
            ro = (float)Math.Round(Math.Atan (WspF / CosKPG),2);
            Console.WriteLine($"Ro wynosi: {ro}");
        }
        private static void WarunekSamohamownosc(float gamma, float ro, int udzwig, float D2)
        {
            if (gamma < ro)
            {
                Console.WriteLine("Warunek samohamowności spełniony");
                /// Moment tarcia
                float angleRoG = ro + gamma;
                float radRoG = (float) (angleRoG * (Math.PI / 180));
                float Ttgw = (float)(0.5 * udzwig * D2 * Math.Tan(radRoG));
                Console.WriteLine($"Moment tarcia {Ttgw}");
            }
            else
            {
                Console.WriteLine("Warunek samohamowności niespełniony");
            }
        }
        static void Main(string[] args)
        {
            ParametryWejsciowe.ZadaneParametry();
            SrubyTrapezoweLista.ListaSrubTrapezowych();
            float D2, D3, podzialka, KatPochGwi, WspF, ro;
            int udzwig;
            PodstawoweParametry(out D2, out D3, out podzialka, out float gamma, out udzwig);
            Ro(out KatPochGwi, out WspF, out ro);
            WarunekSamohamownosc(gamma, ro, udzwig, D2);
            Console.ReadKey();
        }
    }
}
1

Ale zrób to dla własnego komfortu. Jak mówisz o gwoździu to nazywaj obiekt gwóźdź a nie gwoździe bo przez to jest i mi ciężko zrozumieć i idąc dalej tym tokiem udzielić pomocy

0

Mam trochę wolnego czasu i rozbiłem Twoją metodę "PodstawoweParametry". Zobacz to i napisz mi jeżeli czegoś nie rozumiesz a Wytłumaczę to :)

        private static float ObliczD2(float ParametrUdzwig, float WsWysGwintu, float WsWysNakretki, float Kd)
        {
            return (float)Math.Round(Math.Sqrt(ParametrUdzwig / (Math.PI * WsWysGwintu * WsWysNakretki * Kd)), 2);
        }
        private static float ObliczD3(float Beta, float ParametrUdzwig, float Kc)
        {
            return (float)Math.Round(Math.Sqrt((4 * Beta * ParametrUdzwig) / (Math.PI * Kc)), 2);
        }
        // SrubyTrapezoweProperties zamieniłem na SrubaTrapezowaProperty
        private static SrubaTrapezowaProperty DobierzSrube(float D2, float D3, SrubaTrapezowaProperty[] Sruby)
        {
            foreach (SrubaTrapezowaProperty sruba in SrubyTrapezoweLista.sruby)
            {
                if (sruba.SrednicaD2 > D2 & sruba.SrednicaD3 > D3)
                     return sruba;
            }
            return null;
        }
        
        private static void PodstawoweParametry(out float D2, out float D3, out float podzialka, out float gamma, out int udzwig)
        {
            var parametry = new ParametryWejsciowe();
            udzwig = 0;
            podzialka = 0;
            gamma = 0;
            udzwig = parametry.ParametrUdzwig;
            
            D2 = ObliczD2(parametry.ParametrUdzwig, parametry.WsWysGwintu, parametry.WsWysNakretki, parametry.Kd);
            D3 = ObliczD3(parametry.Beta, parametry.ParametrUdzwig, parametry.Kc);
            
            Console.WriteLine($"Średnica d2 = {D2}");
            Console.WriteLine($"Średnica d3 = {D3}");

            SrubaTrapezowaProperty DobranaSruba = DobierzSrube(D2, D3, SrubyTrapezoweLista.sruby.ToArray());
            // Wykona się tylko gdy faktycznie znaleziono śrubę, patrz metodę DobierzSrube
            if (DobranaSruba != null)
            {
                podzialka = (float)DobranaSruba.Podzialka;
                gamma = (float)Math.Round(Math.Atan(podzialka / Math.PI * D2), 2);
                Console.WriteLine($"Dobrano śrubę trapezową: {DobranaSruba.OznaczenieSruby}");
                Console.WriteLine($"Podziałka śruby {podzialka}");
                Console.WriteLine($"Gamma = {gamma}");
            }
            else
            {
                Console.WriteLine("Nie dobrano śruby");
            }
        }

tak by the Way - nie wiem jakie tam obliczenia się kryją ale nie powinno być zamiast

sruba.SrednicaD2 > D2 & sruba.SrednicaD3

tego?

sruba.SrednicaD2 > D2 && sruba.SrednicaD3
0

dzisiaj trochę ogarniałem dokładniej metody i klasy także widzę sens. Tu jest moja dodatkowa klasa ParametryWejsciowe skąd biorę wartości, także bez stworzenia nowego obiektu new ParametryWejsciowe się nie obejdzie ?

using System;
using System.Collections.Generic;
using PodnosnikLibrary;

namespace Podnosnik
{
    class ParametryWejsciowe
    {
        private const string Stal = "20";
        public int ParametrUdzwig { get; set; }
        public int ParametrWznios { get; set; }
        public float WsWysNakretki { get; set; }
        public float WsWysGwintu { get; set; }
        public int Kd { get; set; }
        public float Beta { get; set; }
        public float Kc { get; set; }
        public int Re { get; set; }
        
        
        public ParametryWejsciowe()
        {
            this.ParametrUdzwig = 5000;
            this.ParametrWznios = 300;
            this.WsWysNakretki = 1.5f;
            this.WsWysGwintu = 0.5f;
            this.Kd = 8;
            this.Beta = 1.3f;
            List<Stale> stale = ParametryStaliLista.DoborRe();
            foreach (Stale stal in stale)
            {
                if (stal.ZnakStali == Stal)
                { 
                    this.Re = stal.WartoscReN;
                }
            }
            this.Kc = this.Re / 3;
        }
        public static void ZadaneParametry()
        {
            var zadane = new ParametryWejsciowe();
            Console.WriteLine($"Wartość udźwigu = {zadane.ParametrUdzwig} N");
            Console.WriteLine($"Wartość wzniosu = {zadane.ParametrWznios} mm");
            Console.WriteLine("Pozostałe wartości: \n");
            Console.WriteLine($"Wartość współczynnika wysokości nakrętki = {zadane.WsWysNakretki}");
            Console.WriteLine($"Wartość współczynnika wysokości gwintu = {zadane.WsWysGwintu}");
            Console.WriteLine($"Wartość współczynnika kd = {zadane.Kd}");
            Console.WriteLine($"Wartość Re = {zadane.Re}");
        }
    }
}
0
Grzegorz Świdwa napisał(a):

Mam trochę wolnego czasu i rozbiłem Twoją metodę "PodstawoweParametry". Zobacz to i napisz mi jeżeli czegoś nie rozumiesz a Wytłumaczę to :)

        private static float ObliczD2(float ParametrUdzwig, float WsWysGwintu, float WsWysNakretki, float Kd)
        {
            return (float)Math.Round(Math.Sqrt(ParametrUdzwig / (Math.PI * WsWysGwintu * WsWysNakretki * Kd)), 2);
        }
        private static float ObliczD3(float Beta, float ParametrUdzwig, float Kc)
        {
            return (float)Math.Round(Math.Sqrt((4 * Beta * ParametrUdzwig) / (Math.PI * Kc)), 2);
        }
        // SrubyTrapezoweProperties zamieniłem na SrubaTrapezowaProperty
        private static SrubaTrapezowaProperty DobierzSrube(float D2, float D3, SrubaTrapezowaProperty[] Sruby)
        {
            foreach (SrubaTrapezowaProperty sruba in SrubyTrapezoweLista.sruby)
            {
                if (sruba.SrednicaD2 > D2 & sruba.SrednicaD3 > D3)
                     return sruba;
            }
            return null;
        }
        
        private static void PodstawoweParametry(out float D2, out float D3, out float podzialka, out float gamma, out int udzwig)
        {
            var parametry = new ParametryWejsciowe();
            udzwig = 0;
            podzialka = 0;
            gamma = 0;
            udzwig = parametry.ParametrUdzwig;
            
            D2 = ObliczD2(parametry.ParametrUdzwig, parametry.WsWysGwintu, parametry.WsWysNakretki, parametry.Kd);
            D3 = ObliczD3(parametry.Beta, parametry.ParametrUdzwig, parametry.Kc);
            
            Console.WriteLine($"Średnica d2 = {D2}");
            Console.WriteLine($"Średnica d3 = {D3}");

            SrubaTrapezowaProperty DobranaSruba = DobierzSrube(D2, D3, SrubyTrapezoweLista.sruby.ToArray());
            // Wykona się tylko gdy faktycznie znaleziono śrubę, patrz metodę DobierzSrube
            if (DobranaSruba != null)
            {
                podzialka = (float)DobranaSruba.Podzialka;
                gamma = (float)Math.Round(Math.Atan(podzialka / Math.PI * D2), 2);
                Console.WriteLine($"Dobrano śrubę trapezową: {DobranaSruba.OznaczenieSruby}");
                Console.WriteLine($"Podziałka śruby {podzialka}");
                Console.WriteLine($"Gamma = {gamma}");
            }
            else
            {
                Console.WriteLine("Nie dobrano śruby");
            }
        }

tak by the Way - nie wiem jakie tam obliczenia się kryją ale nie powinno być zamiast

sruba.SrednicaD2 > D2 & sruba.SrednicaD3

tego?

sruba.SrednicaD2 > D2 && sruba.SrednicaD3

sruba.SrednicaD2 > D2 i sruba.SrednicaD3 > D3. oba warunki mają być spełnione

1 użytkowników online, w tym zalogowanych: 0, gości: 1