none
Разработка XML RRS feed

  • Вопрос

  • Добрый день

    С XML знаком очень мало, но очень быстро нужно сделать структуру данных

    Итак, оно должно содержать полную информацию о кафеле

    имя:Modesta
    производитель:Cersanit
    страна производителя:Россия
    
    данные настенного кафеля
    стоимость первого цвета кафеля:1350тг
    длина первого цвета кафеля:0,3м
    ширина первого цвета кафеля:0,2м
    толщина первого цвета кафеля:0,006м
    вес первого цвета кафеля:0,8кг
    штук в коробке первого цвета кафеля:22шт
    ...
    стоимость четвертого цвета кафеля (если есть):
    
    данные напольного кафеля
    стоимость первого цвета кафеля:1550тг
    длина первого цвета кафеля:0,314м
    ширина первого цвета кафеля:0,314м
    толщина первого цвета кафеля:0,009м
    вес первого цвета кафеля:0,95кг
    штук в коробке первого цвета кафеля:12шт
    
    данные декоративного кафеля
    стоимость первого цвета декора:850тг
    вес первого цвета декора:0,85кг
    штук в коробке первого цвета декора:20шт
    
    данные бордюра
    стоимость первого цвета бордюра:400тг
    длина первого цвета бордюра:0,3м
    ширина первого цвета бордюра:0,05м
    вес первого цвета бордюра:0,03кг
    штук в коробке первого цвета бордюра:40шт

    Некоторые коллекции могут иметь от 1 до 4 цветов кафеля, столько же видов бордюров и декоров

    Данный XML файл нужен для сохранения данных в файле(данных коллекции), и с возможностью использование в приложении.

    Каждое свойство очень важна.

    Если это будет удобнее хранить в какой нибудь базе, то покажите как,

    вся проблема в структурировании данных, нужно что бы к свойству кафеля было удобней обращаться, и что не мало важно, делать это с точностью

    Если возникнут вопросы отпишитесь.

    17 сентября 2013 г. 15:21

Ответы

  • Главная заповедь разработчика: "Работает - не трожь!" :) Если всё работает, может так и оставить?

    Гм, гм... Я полагал, что Data - это класс для хранения именно параметров плитки. А тут я вижу параметры бизнес-логики.

    Ладно, предложу тот способ, что хотел изначально.

    Создаём сущности предметной области: классы для каждого вида плитки:

    public partial class WallTile
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Length { get; set; }
        public double Width { get; set; }
        public double Thickness { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }
    
    public partial class FloorTile
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Length { get; set; }
        public double Width { get; set; }
        public double Thickness { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }
    
    public partial class DecorativeTile
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }
    
    public partial class Border
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Length { get; set; }
        public double Width { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }

    Предполагается, что с экземплярами этих классов будет удобно работать:

    WallTile wallTile1 = new WallTile();
    wallTile1.Color = "Red";
    wallTile1.Cost = 555;
    
    WallTile wallTile2 = new WallTile();
    wallTile2.Color = "Green";
    wallTile2.Number = 20;
    
    Border border1 = new Border();
    border1.Length = 100;
    border1.Weight = 0.2;
    
    // далее их можно использовать в коде


    Создаём класс, который будет содержать информацию о всей продукции, выпускаемой производителем:

    public partial class Data
    {
        public string Name { get; set; }
        public string Maker { get; set; }
        public string Country { get; set; }
    
        public List<WallTile> WallTiles { get; set; }
        public List<FloorTile> FloorTiles { get; set; }
        public List<DecorativeTile> DecorativeTiles { get; set; }
        public List<Border> Borders { get; set; }
    }


    Заполняем свойства этого класса, и добавляем в коллекции ранее созданные экземпляры плитки:

    Data data = new Data();
    
    data.Name = "Foo";
    data.Maker = "Bar";
    data.Country = "Russia";
    
    data.WallTiles = new List<WallTile>();
    data.Borders = new List<Border>();
    
    data.WallTiles.Add(wallTile1);
    data.WallTiles.Add(wallTile2);
    
    data.Borders.Add(border1);

    Когда у нас имеются такие доменные классы, их очень просто записывать и считывать с помощью сериализации:

    XmlSerializer ser = new XmlSerializer(typeof(Data));
    
    using (var fs = new FileStream("data.xml", FileMode.Create))
    {
        ser.Serialize(fs, data);
    }
    
    Data data2;
    using (var fs = new FileStream("data.xml", FileMode.Open))
    {
        data2 = (Data)ser.Deserialize(fs);
    }

    • Помечено в качестве ответа Medet Tleukabiluly 17 сентября 2013 г. 21:37
    17 сентября 2013 г. 20:34

Все ответы

  • В дотнете большой выбор API для работы с XML. Так что подберём оптимальный.

    Вопросы:

    • Каков предполагаемый размер файлов? Если очень большой - от гигабайта и выше, то только потоковый API подходит.
    • Предполагается ли использование этих файлов XML в другом софте? Обмен с другими клиентами? Если да, то желательно сделать XmlSchema.
    • Эти данные нужно валидировать? То есть можно ли им доверять? Для валидации нужно составить XmlSchema.
    • Какой язык используется? Я не ошибся, что речь о дотнете?
    • Имеется ли уже какой-нибудь код (например, на C#), к которому нужно подогнать структуру xml? Хочу его видеть. Если кода нет, то хотелось бы получить хоть какой-то набросок.

    Насчёт хранения в базе данных. Если данных очень много (все сразу не влезают в оперативку), и нужен быстрый доступ к любой части данных, то тогда, конечно, обязательно использование БД.

    17 сентября 2013 г. 17:02
    1. Размеры минимальны. Простой файл для описания коллекции "Модеста", 1 файл = 1 коллекция.
    2. На другом софте использовать не нужно
    3. Конечно нужно доверять, ведь они и есть те данные на что опирается сам процесс подсчета
    4. Dot.Net в частности c#

    5. под каждую переменную хотелось бы использовать данные из xml

    static class Calculator
        {
            static public double BasicFloorArea(double RoomX, double RoomY, double BathExistFloor, double BathX, double BathY)
            {
                return (RoomX*RoomY) - ((BathX*BathY)/2)*BathExistFloor;
            }
            static public double BasicBlackArea(double RoomX, double RoomY, double DoorX, double SmallHight, double BathExist, double BathX, double BathY, double BathH, double twh)
            {
                double ddd = 0;
                if (SmallHight * twh >= BathH)
                {
                    if (BathExist == 4)
                        ddd = (RoomX + RoomY) * 2 * SmallHight * twh - DoorX * SmallHight * twh - (BathX + BathY + BathY) * BathH;
                    else if (BathExist == 3)
                        ddd = (RoomX + RoomY) * 2 * SmallHight * twh - DoorX * SmallHight * twh - (BathX + BathY) * BathH;
                    else if (BathExist == 0)
                        ddd = (RoomX + RoomY) * 2 * SmallHight * twh - DoorX * SmallHight * twh;
                }
                else if (SmallHight * twh < BathH)
                {
                    if (BathExist == 4)
                        ddd = (RoomX + RoomY) * 2 * SmallHight * twh - DoorX * SmallHight * twh - ((BathX + BathY + BathY) * SmallHight*twh);
                    else if (BathExist == 3)
                        ddd = (RoomX + RoomY) * 2 * SmallHight * twh - DoorX * SmallHight * twh - ((BathX + BathY) * SmallHight*twh);
                    else if (BathExist == 0)
                        ddd = (RoomX + RoomY) * 2 * SmallHight * twh - DoorX * SmallHight * twh;
    
                }
                return ddd;
            }
            static public double BasicWhiteArea(double RoomX, double RoomY, double RoomH, double DoorX, double DoorH, double SmallHight, double decor, double twx, double twh)
            {
                return (RoomX + RoomY) * 2 * (RoomH - (SmallHight * twh)) - DoorX * (DoorH - (SmallHight * twh)) - decor * twx * twh;
            }
            static public double BasicBorder(double RoomX, double RoomY, double DoorX,double twx, double vb)
            {
                return (((RoomX+RoomY)*2-DoorX)/twx)*vb;
            }
    
            static public double BasicBlackAreaExpert(double RoomX, double RoomY, double DoorX, double SmallHight, double BathExist, double BathX, double BathY, double BathH, double twh)
            {
                double tempo = 0;
                double BathExistArea = 0;
                if (SmallHight * twh >= BathH)
                {
                    if (BathExist == 0)
                    { BathExistArea = 0; }
                    else if (BathExist == 3)
                    { BathExistArea = BathH * BathX + BathH * BathY; }
                    else if (BathExist == 4)
                    { BathExistArea = (BathH * BathX) + (BathH * BathY) + (BathH * BathY); }
                }
                else if (0<SmallHight * twh && SmallHight*twh< BathH)
                {
                    if (BathExist == 0)
                    { BathExistArea = 0; }
                    else if (BathExist == 3)
                    { BathExistArea = (BathH - SmallHight * twh) * BathX + (BathH - SmallHight * twh) * BathY; }
                    else if (BathExist == 4)
                    { BathExistArea = (BathH - SmallHight * twh) * (BathX + BathY + BathY); }
                }
                else if (SmallHight * twh == 0)
                {
                    BathExistArea = 0;
                }
                tempo = ((RoomX+RoomY)*2*SmallHight*twh) - DoorX*SmallHight*twh - BathExistArea;
    
                return tempo; 
            }
            static public double BasicWhiteAreaExpert(double RoomX, double RoomY, double RoomH, double DoorX, double DoorH, double SmallHight, double BathExist, double BathX, double BathY, double BathH, double twh, double twx, double decor)
            {
                double tempor = 0;
                double BathExistArea1 = 0;
                if (SmallHight * twh < BathH)
                {
                    if (BathExist == 0)
                    { BathExistArea1 = 0; }
                    else if (BathExist == 3)
                    { BathExistArea1 = (BathH - SmallHight * twh) * BathX + (BathH - SmallHight * twh) * BathY; }
                    else if (BathExist == 4)
                    { BathExistArea1 = (BathH - SmallHight * twh) * BathX + (BathH - SmallHight * twh) * BathY + ((BathH - SmallHight * twh) * BathY); }
                }
                tempor = ((RoomX + RoomY) * 2 * (RoomH - SmallHight * twh) - DoorX * (DoorH - SmallHight * twh)) - BathExistArea1 - decor * twh * twx;
                    
                return tempor; }
            //prosmotret' pillarwhite + pillar black!!!!!!!!!!!!!!!!!!!!!!!!!11
            static public double PillarBlackArea(double RoomX, double RoomY, double RoomH, double DoorX, double DoorH, double SmallHight, double BathExist, double BathX, double BathY, double BathH, double twh, double twx, double pillarfatness, double pillarbeltfatness, double elementperwall, double walls)
            {
                double BathExistArea = 0;
    
                if (SmallHight * twh >= BathH)
                {
                    if (BathExist == 0)
                    { BathExistArea = 0; }
                    else if (BathExist == 3)
                    { BathExistArea = BathH * (BathX - twx * pillarfatness * elementperwall) + BathH * (BathY - twx * pillarfatness); }
                    else if (BathExist ==4)
                    { BathExistArea = (BathH * (BathX - (twx * pillarfatness * elementperwall))) + (BathH * (BathY - twx * pillarfatness)) + (BathH * (BathY - twx * pillarfatness)); }
                }
                else if (SmallHight * twh < BathH)
                {
                    if (BathExist == 0)
                    { BathExistArea = 0; }
                    else if (BathExist == 3)
                    { BathExistArea = (BathH - SmallHight * twh) * (BathX - twx * elementperwall*pillarfatness) + (BathH - SmallHight * twh) * (BathY - twx * elementperwall*pillarfatness); }
                    else if (BathExist == 4)
                    { BathExistArea = (BathH - SmallHight * twh) * (BathX - twx * elementperwall*pillarfatness) + (BathH - SmallHight * twh) * (BathY - twx * elementperwall*pillarfatness) + (BathH - SmallHight * twh) * (BathY - twx * elementperwall*pillarfatness); }
                }
                return ((((RoomX + RoomY) * 2) * SmallHight * twh) - (DoorX * SmallHight * twh) + (((RoomX + RoomY) * 2) * twh * pillarbeltfatness) - (DoorX * twh * pillarbeltfatness) + ((RoomH - (SmallHight * twh) - (twh * pillarbeltfatness)) * pillarfatness * twx * elementperwall * walls) - BathExistArea);
            }
            static public double PillarWhiteArea(double RoomX, double RoomY, double RoomH, double DoorX, double DoorH, double SmallHight, double BathExist, double BathX, double BathY, double BathH, double twh, double twx, double pillarfatness, double pillarbeltfatness, double elementperwall, double walls, double dec)
            {
                double BathExistArea = 0;
                if (SmallHight * twh >= BathH)
                { BathExistArea = 0; }
                else if (SmallHight * twh < BathH)
                {
                    if (BathExist == 0)
                    { BathExistArea = 0; }
                    else if (BathExist == 3)
                    { BathExistArea = (BathH - SmallHight * twh) * ((BathX - twx * pillarfatness * elementperwall) + (BathY - twx * pillarfatness)); }
                    else if (BathExist == 4)
                    { BathExistArea = (BathH - SmallHight * twh) * ((BathX - (twx * pillarfatness * elementperwall)) + (BathY - (twx * pillarfatness)) + (BathY - (twx * pillarfatness))); }
                }
                return (((RoomX + RoomY) * 2 * (RoomH - (SmallHight * twh))) - (DoorX * (DoorH - SmallHight * twh- twh*pillarbeltfatness)) - ((RoomX + RoomY) * 2 * (twh * pillarbeltfatness)) - (dec * twh * twx) - ((RoomH - (SmallHight * twh)- twh*pillarbeltfatness) * twx * pillarfatness * elementperwall * walls) -BathExistArea);
            }
    
            static public double ExpertGetBorder(double RoomX, double RoomY, double RoomH, double DoorX, double twh, double twx, double vb, double BorderPos, double BorderOverDoor)
            {
                double temp = 0;
                if (Data.Vb == 0)
                {
                    temp = 0;
                }
                else if (Data.Vb == 1)
                {
                    if (Data.BorderPosition == 0)
                    {
                        temp = ((RoomX + RoomY) * 2 - DoorX) / twx;
                    }
                    else if (Data.BorderPosition == 1)
                    {
                        temp = RoomH / twh;
                    }
                }
                else if (Data.Vb == 2)
                {
                    if (Data.BorderOverDoor == 0)
                    {
                        temp = ((RoomX + RoomY) * 2 - DoorX) / twx + ((RoomX + RoomY) * 2 - DoorX) / twx;
                    }
                    else if (Data.BorderOverDoor == 1)
                    {
                        temp = ((RoomX + RoomY) * 2 - DoorX) / twx + ((RoomX + RoomY) * 2) / twx;
                    }
                }
                else
                {
                    temp = (((RoomX + RoomY) * 2 - DoorX) / twx) * Data.Vb ;
                }
                return temp;
            }

    на данный момент используется обычный txt файл для хранения,

    private void OpenFileButton_Click(object sender, EventArgs e)
            {
                if (ofd.FileName != String.Empty)
                {
                    FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
    
                    StreamReader r = new StreamReader(fs);
                    // Read data from Test.data.
                    for (int i = 0; i < 1; i++)
                    {
    
                        (Data.ProjectName) = r.ReadLine();
                        (Data.DateTime) = r.ReadLine();
                        (Data.RoomX) = Convert.ToDouble(r.ReadLine());
                        (Data.RoomY) = Convert.ToDouble(r.ReadLine());
                        (Data.RoomH) = Convert.ToDouble(r.ReadLine());
                        (Data.DoorX) = Convert.ToDouble(r.ReadLine());
                        (Data.DoorH) = Convert.ToDouble(r.ReadLine());
                        (Data.BathE) = Convert.ToDouble(r.ReadLine());
                        (Data.BathEF) = Convert.ToDouble(r.ReadLine());
                        (Data.BathX) = Convert.ToDouble(r.ReadLine());
                        (Data.BathY) = Convert.ToDouble(r.ReadLine());
                        (Data.BathH) = Convert.ToDouble(r.ReadLine());
                        Data.Vsh = Convert.ToDouble(r.ReadLine());
                        (Data.Border) = Convert.ToDouble(r.ReadLine());
                        (Data.Dec) = Convert.ToDouble(r.ReadLine());
                        (Data.TileWh) = Convert.ToDouble(r.ReadLine());
                        (Data.TileWx) = Convert.ToDouble(r.ReadLine());
                        (Data.TileFh) = Convert.ToDouble(r.ReadLine());
                        (Data.TileFx) = Convert.ToDouble(r.ReadLine());
                        (Data.White) = Convert.ToDouble(r.ReadLine());
                        (Data.Black) = Convert.ToDouble(r.ReadLine());
                        (Data.Floor) = Convert.ToDouble(r.ReadLine());
                        Data.Walls = Convert.ToDouble(r.ReadLine());
                        Data.ElementsPerWall = Convert.ToDouble(r.ReadLine());
                        Data.PillarFatness = Convert.ToDouble(r.ReadLine());
                        Data.PillarBeltFatness = Convert.ToDouble(r.ReadLine());
                        Data.Vb = Convert.ToDouble(r.ReadLine());
                        Data.BorderPosition = Convert.ToDouble(r.ReadLine());
                        Data.BorderOverDoor = Convert.ToDouble(r.ReadLine());
                        (Data.Mode) = r.ReadLine();
                        (Data.Error) = Convert.ToBoolean(r.ReadLine());
                        (Data.ErrorType) = r.ReadLine();
                        Data.Excess = Convert.ToDouble(r.ReadLine());
                        (Data.GlueProportion) = Convert.ToDouble(r.ReadLine());
                        (Data.SpacerProportion) = Convert.ToDouble(r.ReadLine());
                        (Data.WeightProportionW) = Convert.ToDouble(r.ReadLine());
                        (Data.WeightProportionF) = Convert.ToDouble(r.ReadLine());
                        (Data.BoxProportionW) = Convert.ToDouble(r.ReadLine());
                        (Data.BoxProportionF) = Convert.ToDouble(r.ReadLine());
                        Data.Wcost = Convert.ToDouble(r.ReadLine());
                        Data.Fcost = Convert.ToDouble(r.ReadLine());
                        Data.Dcost = Convert.ToDouble(r.ReadLine());
                        Data.Bcost = Convert.ToDouble(r.ReadLine());
                        Data.Gcost = Convert.ToDouble(r.ReadLine());
                        Data.Tcost = Convert.ToDouble(r.ReadLine());
    
                    }
                    RESULT res = new RESULT();
                    res.Show();
                    res.Location = new Point(220, 100);
                }
                else
                {
                    MessageBox.Show("ошибка при чтений");
                    return;
                }
            }

    это все не очень устраивает.

    Вероятней всего лучше использовать базу данных. Но как представить такию схему при наличии разности коллекции?

    17 сентября 2013 г. 17:18
  • Очень хорошо. Но главное, что я хотел видеть - структуру для хранения данных. То есть класс Data.

    17 сентября 2013 г. 17:36
  • Но это простой класс с открытыми свойствами, как бы временное хранилище данных для "подсчета", в нем нет ничего особенного,

    присваиваю>процесс подсчета>удаляю


    static class Data
        {
            public static string ProjectName { get; set; } //100
            public static string DateTime { get; set; } //101
    
            public static double RoomX { get; set; } //110
            public static double RoomY { get; set; } //111
            public static double RoomH { get; set; } //112
            public static double DoorX { get; set; } //113
            public static double DoorH { get; set; } //114
    
            public static double BathE { get; set; } //120
            public static double BathEF { get; set; } //124
            public static double BathX { get; set; } //121
            public static double BathY { get; set; } //122
            public static double BathH { get; set; } //123
    
            public static double Vsh { get; set; }
    
            public static double Border { get; set; } //129
            public static double Dec { get; set; } //130
            public static double TileWh { get; set; } //131
            public static double TileWx { get; set; } //132
            public static double TileFh { get; set; } //133
            public static double TileFx { get; set; } //134
    
            public static double White { get; set; } //140
            public static double Black { get; set; } //141
            public static double Floor { get; set; } //142
    
            public static double Walls { get; set; }
            public static double ElementsPerWall { get; set; }
            public static double PillarFatness { get; set; }
            public static double PillarBeltFatness { get; set; }
    
            public static double Vb { get; set; }
            public static double BorderPosition { get; set; }
            public static double BorderOverDoor { get; set; }
    
    
            public static string Mode { get; set; } //150
    
            public static bool Error {get; set;} //200
            public static string ErrorType { get; set; } // 201
    
            public static double Excess { get; set; } //255
    
    
            public static double GlueProportion { get; set; }
            public static double SpacerProportion { get; set; }
            public static double WeightProportionW { get; set; }
            public static double WeightProportionF { get; set; }
            public static double BoxProportionW { get; set; }
            public static double BoxProportionF { get; set; }
    
            public static double Wcost { get; set; }
            public static double Fcost { get; set; }
            public static double Dcost { get; set; }
            public static double Bcost { get; set; }
            public static double Gcost { get; set; }
            public static double Tcost { get; set; }
    
    
        }

    может это совсем не правильно, но все работает без отказно

    17 сентября 2013 г. 18:49
  • Главная заповедь разработчика: "Работает - не трожь!" :) Если всё работает, может так и оставить?

    Гм, гм... Я полагал, что Data - это класс для хранения именно параметров плитки. А тут я вижу параметры бизнес-логики.

    Ладно, предложу тот способ, что хотел изначально.

    Создаём сущности предметной области: классы для каждого вида плитки:

    public partial class WallTile
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Length { get; set; }
        public double Width { get; set; }
        public double Thickness { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }
    
    public partial class FloorTile
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Length { get; set; }
        public double Width { get; set; }
        public double Thickness { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }
    
    public partial class DecorativeTile
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }
    
    public partial class Border
    {
        public string Color { get; set; }
        public decimal Cost { get; set; }
        public double Length { get; set; }
        public double Width { get; set; }
        public double Weight { get; set; }
        public int Number { get; set; }
    }

    Предполагается, что с экземплярами этих классов будет удобно работать:

    WallTile wallTile1 = new WallTile();
    wallTile1.Color = "Red";
    wallTile1.Cost = 555;
    
    WallTile wallTile2 = new WallTile();
    wallTile2.Color = "Green";
    wallTile2.Number = 20;
    
    Border border1 = new Border();
    border1.Length = 100;
    border1.Weight = 0.2;
    
    // далее их можно использовать в коде


    Создаём класс, который будет содержать информацию о всей продукции, выпускаемой производителем:

    public partial class Data
    {
        public string Name { get; set; }
        public string Maker { get; set; }
        public string Country { get; set; }
    
        public List<WallTile> WallTiles { get; set; }
        public List<FloorTile> FloorTiles { get; set; }
        public List<DecorativeTile> DecorativeTiles { get; set; }
        public List<Border> Borders { get; set; }
    }


    Заполняем свойства этого класса, и добавляем в коллекции ранее созданные экземпляры плитки:

    Data data = new Data();
    
    data.Name = "Foo";
    data.Maker = "Bar";
    data.Country = "Russia";
    
    data.WallTiles = new List<WallTile>();
    data.Borders = new List<Border>();
    
    data.WallTiles.Add(wallTile1);
    data.WallTiles.Add(wallTile2);
    
    data.Borders.Add(border1);

    Когда у нас имеются такие доменные классы, их очень просто записывать и считывать с помощью сериализации:

    XmlSerializer ser = new XmlSerializer(typeof(Data));
    
    using (var fs = new FileStream("data.xml", FileMode.Create))
    {
        ser.Serialize(fs, data);
    }
    
    Data data2;
    using (var fs = new FileStream("data.xml", FileMode.Open))
    {
        data2 = (Data)ser.Deserialize(fs);
    }

    • Помечено в качестве ответа Medet Tleukabiluly 17 сентября 2013 г. 21:37
    17 сентября 2013 г. 20:34