powered by simpleCommunicator - 2.0.28     © 2024 Programmizd 02
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Хозяйке на заметку
16 сообщений из 16, страница 1 из 1
Хозяйке на заметку
    #40130849
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот буду сюда кидать всякие сниппеты.
Берите пользуйтесь если надо. Копируйте себе в сорцы без ограничений.

1) Конвертит картинку в псевдографику. Можно в чяте печатать QR-коды. Только шрифты подобрать.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
    public static final double GK=0.587;
    public static final double BK=0.114;
    public static final double RK=0.299;

    public static void main(String[] args) throws IOException {
        BufferedImage i = ImageIO.read(new FileInputStream(args[0]));
        PrintWriter p = new PrintWriter(new FileWriter(args[1], StandardCharsets.UTF_8));
        boolean inverse = false;
        if (args.length == 3) {
            inverse = Boolean.getBoolean(args[2]);
        }

        //                             y    |   y + 1
        //                      ---------------------
        char[] c = {' ',        //     0        0
                   '▄',    // ▄   0        1
                   '▀',    // ▀   1        0
                   '█' };  // █   1        1
        for (int y = 0; y < i.getWidth(); y+=2) {
            for (int x = 0; x < i.getWidth(); x++) {
                int pix1 = decodeY(i.getRGB(x,y))     > 0.5 ? 0x1 : 0x0;
                int pix2 = decodeY(i.getRGB(x,y + 1)) > 0.5 ? 0x1 : 0x0;
                int index = (pix1 << 1) | pix2;
                p.print(c[inverse ? 3 - index : index]);
            }
            p.println();
        }
        p.close();
    }

    private static double decodeY(int color) {
        return  (GK * ((color & 0x00FF00) >> 8) + BK * (color & 0x0000FF) + RK * ((color & 0xFF0000) >> 16)) / 255.0;
    }
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40130892
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот в тексте как-то так выглядит.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
$ cat out.txt 
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████ ▄▄▄▄▄ █▀▀ ██   ▄  ▄ █ ▄▄▄▄▄ ███████████
██████████ █   █ █▄▀██▀▀▄██▄▀▀▄█ █   █ ███████████
██████████ █▄▄▄█ █ ▄ █ █▄  ▀ ▀▀█ █▄▄▄█ ███████████
██████████▄▄▄▄▄▄▄█ █ ▀▄▀▄█▄▀ █ █▄▄▄▄▄▄▄███████████
██████████  ▀ ▀█▄▄█▀█  ▀▄▄ ▀██▀█ ▄▄▀▄▄▀███████████
████████████▄▀▄█▄▄▀▀▀   ▄█▄█▀▄█ █▀▀▄  ████████████
██████████▄▀▀█▀▄▄█ █▄ █▀ █▄▄█   ▄▀█▄█▄▄███████████
██████████▄▀▄▀ ▄▄ ███ █▄▄█ ▀██▄▀███ ▄ ▄███████████
██████████▄▀█▀ ▄▄█▄▀██  ▀▄█▄█▄▄ ▀ █▀█▄▀███████████
██████████▄█ █ ▄▄█ █ ▄ █ █ ▀▀▀▄▄ ▄███  ███████████
██████████▄██▄██▄▄ ▄█▀██▀█▀▀▀█ ▄▄▄ █ ▀▀███████████
██████████ ▄▄▄▄▄ █▄▀▀███▀█ ▄▄█ █▄█ ▀▀▄████████████
██████████ █   █ █▀ ▄▀ ██▄▄ █▀▄  ▄ ▀▀ ▄███████████
██████████ █▄▄▄█ █▀▄▄█ ▀▀▀   █▀█▀█ ▄▄▀▄███████████
██████████▄▄▄▄▄▄▄█▄█▄▄█▄▄█▄▄██▄▄█▄▄██▄████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
██████████████████████████████████████████████████
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40130961
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выглядит интересно, продолжай )
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40130962
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спосибо.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40131063
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот еще такая штука. Писал лет 10 назад по мотивам Oracle DBMS_APPLICATION_INFO пакета.

Потом переписал чтоб современнее смотрелась.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

import static java.lang.String.format;
import static java.time.Instant.ofEpochMilli;
import static org.apache.commons.io.FileUtils.byteCountToDisplaySize;
import static org.apache.commons.lang3.time.DurationFormatUtils.formatDuration;

public class SofarTracker {

    private static final String INTERVAL_TIME_FORMAT = "H:mm:ss";
    private static final String UNKNOWN_INTERVAL_PLACEHOLDER = "??:??:??";
    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public long getSize() {
        return size;
    }

    public long getPosition() {
        return position;
    }

    enum UnitTypes {
        UNITS, BYTES
    }

    private String units;

    private long size;

    private long position;

    private long startTime;

    private long currentTime;

    private UnitTypes unitType;

    private boolean finished;

    public static SofarTracker createUnitLikeTracker(String units, long size) {
        return new SofarTracker(units, size, UnitTypes.UNITS);
    }

    public static SofarTracker createFileSizeTracker(long size) {
        return new SofarTracker(null, size, UnitTypes.BYTES);
    }

    private SofarTracker(String units, long size, UnitTypes unitType) {
        if (size < 0) {
            throw new IllegalArgumentException(format("Argument was %d but expected nonnegative", position));
        }
        this.units = units;
        this.size = size;
        this.startTime = System.currentTimeMillis();
        this.currentTime = startTime;
        this.unitType = unitType;
    }

    public void update(long position) {
        if (finished == true) {
            throw new IllegalStateException("Unable to update! SofarTracker is finished!");
        }
        if (position < 0 || position > this.size) {
            throw new IllegalArgumentException(format("Argument was %d but expected in interval [0..size]", position));
        }
        this.position = position;
        this.currentTime = System.currentTimeMillis();
    }

    private Optional<Long> estimatedEndTime() {
        if (position == 0) {
            return Optional.empty();
        }
        return Optional.of((long) ((double) size * (currentTime - startTime) / position) + startTime);
    }

    private int calculatePercent() {
        return (int) (100L * position / size);
    }

    private String formatUnitsSpeed() {
        long deltaTimeSec = (currentTime - startTime) / 1000;
        if (deltaTimeSec == 0) {
            return "?";
        } else {
            return String.format("%d %s(s)/sec", position / deltaTimeSec, units);
        }
    }

    private String formatFileSizeSpeed() {
        long deltaTimeSec = (currentTime - startTime) / 1000;
        if (deltaTimeSec == 0) {
            return "?";
        } else {
            return String.format("%s/sec", byteCountToDisplaySize(position / deltaTimeSec));
        }
    }

    private String formatEstimatedEndTime() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
        if (estimatedEndTime().isPresent()) {
            long estimatedEntTimeValue = estimatedEndTime().get();
            return formatter.format(LocalDateTime.ofInstant(ofEpochMilli(estimatedEntTimeValue), ZoneId.systemDefault()));
        } else {
            return UNKNOWN_INTERVAL_PLACEHOLDER;
        }
    }

    @Override
    public String toString() {
        if (finished) {
            if (this.unitType == UnitTypes.BYTES) {
                return format("Done! Processed %s of %s. [ %d%% ] Time elapsed: %s",
                        byteCountToDisplaySize(position),
                        byteCountToDisplaySize(size),
                        calculatePercent(),
                        formatElapsedTime()
                );
            } else {
                return format("Done! Processed %d of %d %s(s). [ %d%% ] Time elapsed: %s",
                        position,
                        size,
                        units,
                        calculatePercent(),
                        formatElapsedTime()
                );
            }
        } else {
            if (this.unitType == UnitTypes.BYTES) {
                return format("Processed %s of %s. [ %d%% ] with avg speed: %s. Time elapsed: %s, Time remain: %s, Will end at %s",
                        byteCountToDisplaySize(position),
                        byteCountToDisplaySize(size),
                        calculatePercent(),
                        formatFileSizeSpeed(),
                        formatElapsedTime(),
                        formatTimeRemains(),
                        formatEstimatedEndTime()
                );
            } else {
                return format("Processed %d of %d %s(s). [ %d%% ] with avg speed: %s. Time elapsed: %s, Time remain: %s, Will end at %s",
                        position,
                        size,
                        units,
                        calculatePercent(),
                        formatUnitsSpeed(),
                        formatElapsedTime(),
                        formatTimeRemains(),
                        formatEstimatedEndTime()
                );
            }
        }
    }

    private String formatTimeRemains() {
        if (estimatedEndTime().isPresent() && estimatedEndTime().get() - currentTime >= 0) {
            return formatDuration(Duration.between(
                    ofEpochMilli(currentTime),
                    ofEpochMilli(estimatedEndTime().get())).toMillis(),
                    INTERVAL_TIME_FORMAT,
                    true);
        } else {
            return UNKNOWN_INTERVAL_PLACEHOLDER;
        }
    }

    private String formatElapsedTime() {
        return formatDuration(Duration.between(
                ofEpochMilli(startTime),
                ofEpochMilli(currentTime)).toMillis(),
                INTERVAL_TIME_FORMAT,
                true);
    }

    public void finish() {
        finished = true;
        position = size;
    }

}



Писал чтоб в логах трекать исполнение очень долгих ETL-процессов которые по суткам работают.
Мне нужно было прогнозировать сколько времени осталось. И видеть сколько строк обработано.
Вот лог как-то так выглядит.

Код: java
1.
2.
3.
4.
5.
6.
7.
Processed 0 of 25000 row(s). [ 0% ] with avg speed: ?. Time elapsed: 0:00:00, Time remain: ??:??:??, Will end at ??:??:??
Processed 9119 of 25000 row(s). [ 36% ] with avg speed: 1013 row(s)/sec. Time elapsed: 0:00:09, Time remain: 0:00:16, Will end at 2022-02-01 15:54:34
Processed 16523 of 25000 row(s). [ 66% ] with avg speed: 1032 row(s)/sec. Time elapsed: 0:00:16, Time remain: 0:00:08, Will end at 2022-02-01 15:54:34
Processed 17343 of 25000 row(s). [ 69% ] with avg speed: 1020 row(s)/sec. Time elapsed: 0:00:17, Time remain: 0:00:07, Will end at 2022-02-01 15:54:34
Processed 21723 of 25000 row(s). [ 86% ] with avg speed: 1034 row(s)/sec. Time elapsed: 0:00:21, Time remain: 0:00:03, Will end at 2022-02-01 15:54:34
Processed 22563 of 25000 row(s). [ 90% ] with avg speed: 1025 row(s)/sec. Time elapsed: 0:00:22, Time remain: 0:00:02, Will end at 2022-02-01 15:54:34
Done! Processed 25000 of 25000 row(s). [ 100% ] Time elapsed: 0:00:22



В качестве юнитов измерений могут быть bytes (если парсим файл) или rows или любые объекты когда например
процессим табличку.

Код: java
1.
2.
3.
4.
5.
// собираемся парсить табличку на 10 тыщ строк.
SofarTracker sofarTrackerTab = SofarTracker.createUnitLikeTracker("row", 10_000);

// собираемся парсить какую-то бинарную колбасу длиной 1 Гиг
SofarTracker sofarTrackerKolbasa = SofarTracker.createFileSizeTracker(1 * 1024 * 1024 * 1024);



метод update можно вызывать когда угодно во времени. Прогноз будет соотв корректироваться.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40131064
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код требует некого рефакторинга - поэтому welcome. Улучшайте. Берите себе если надо.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40131207
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оберточка над ResultSet. Для стриминговой обработки.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import java.sql.ResultSet;

public class StreamUtils {

    static Logger logger = LoggerFactory.getLogger(StreamUtils.class);

    public static <T> Stream<T> toStream(Iterator<T> iterator) {
        return StreamSupport.stream(Spliterators.spliterator(
                iterator,
                Integer.MAX_VALUE,
                Spliterator.IMMUTABLE), false);
    }

    public static <T> Stream<T> toStream(Iterable<T> iterable) {
        return StreamSupport.stream(iterable.spliterator(), false);
    }

    public static <T> Iterator<T> toIterator(Class<T> clazz, ResultSet resultSet) {
        return new Iterator<T>() {
            @Override
            public boolean hasNext() {
                try {
                    return resultSet.next();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public T next() {
                T inst;
                try {
                    inst = clazz.getDeclaredConstructor().newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                for(Field field : clazz.getDeclaredFields()) {
                    field.setAccessible(true);
                    try {
                        Column column = field.getAnnotation(Column.class);
                        if (column != null) {
                            Object value = column.name().isBlank() ? resultSet.getObject(field.getName()) : resultSet.getObject(column.name());
                            field.set(inst, value);
                        }
                    } catch (IllegalAccessException | SQLException e) {
                        throw new RuntimeException(e);
                    }
                }
                return inst;
            }
        };
    }

    public static Iterator<List<Object>> toIterator(int columns, ResultSet resultSet) {

        return new Iterator<List<Object>>() {
            @Override
            public boolean hasNext() {
                try {
                    return resultSet.next();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public List<Object> next() {
                List<Object> list = new ArrayList<>();
                for(int i=0;i<columns;i++) {
                    try {
                        list.add(resultSet.getObject(i + 1));
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    }
                }
                return list;
            }
        };
    }

}



Много чего не поддерживает. Поэтому требует доработки.

Использовать можно как-то так.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public class GeoIp {

    @Column(name = "startipnum")
    private String startipnum;

    @Column(name = "endipnum")
    private String endipnum;

    @Column(name = "lattitude")
    private double lat;

    @Column 
    private double longitude;

  ....
}


  ResultSet resultSet = statement.executeQuery("select * from geoipcity");

        Stream<GeoIp> stream = toStream(toIterator(GeoIp.class, resultSet));
        stream.filter(geoip -> geoip.getLat() > 0.0 && geoip.getLat() < 30.0)
                .forEach(item -> System.out.println(item));



Не требует внешних зависимостей. Только JPA аннотации. Впрочем можно из заменить на свои любые.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40131213
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton

Много чего не поддерживает. Поэтому требует доработки.


чет оно на hasNext() курсор двигает, а не должно
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40131215
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Точняк. Надо дорабатывать.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40131226
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
Код: java
1.
                    field.setAccessible(true);

Я бы сказал, что это - на помойку.
Вне зависимости от "доброты" ваших намерений.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40133589
coceba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton
Вот буду сюда кидать всякие сниппеты.
Берите пользуйтесь если надо. Копируйте себе в сорцы без ограничений.

1) Конвертит картинку в псевдографику. Можно в чяте печатать QR-коды. Только шрифты подобрать.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
    public static final double GK=0.587;
    public static final double BK=0.114;
    public static final double RK=0.299;

    public static void main(String[] args) throws IOException {
        BufferedImage i = ImageIO.read(new FileInputStream(args[0]));
        PrintWriter p = new PrintWriter(new FileWriter(args[1], StandardCharsets.UTF_8));
        boolean inverse = false;
        if (args.length == 3) {
            inverse = Boolean.getBoolean(args[2]);
        }

        //                             y    |   y + 1
        //                      ---------------------
        char[] c = {' ',        //     0        0
                   '▄',    // &#9604;   0        1
                   '▀',    // &#9600;   1        0
                   '█' };  // &#9608;   1        1
        for (int y = 0; y < i.getWidth(); y+=2) {
            for (int x = 0; x < i.getWidth(); x++) {
                int pix1 = decodeY(i.getRGB(x,y))     > 0.5 ? 0x1 : 0x0;
                int pix2 = decodeY(i.getRGB(x,y + 1)) > 0.5 ? 0x1 : 0x0;
                int index = (pix1 << 1) | pix2;
                p.print(c[inverse ? 3 - index : index]);
            }
            p.println();
        }
        p.close();
    }

    private static double decodeY(int color) {
        return  (GK * ((color & 0x00FF00) >> 8) + BK * (color & 0x0000FF) + RK * ((color & 0xFF0000) >> 16)) / 255.0;
    }


Огого, благодарю за код . Будет полезен!
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40133774
adminDontSleep
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton,интересно зачем это все если уже и так все есть для этого)
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40133780
adminDontSleep
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Андрей Панфилов
mayton

Много чего не поддерживает. Поэтому требует доработки.


чет оно на hasNext() курсор двигает, а не должно

это попадос) майтон не в курсах что хезнекст не должен менять состояние итератора а лишь сообщать если ли там след элемент)
за это предлагаю майтона прелюдно отпорицать ,чтобы в дальнейшем не повадно было)
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40133781
adminDontSleep
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. Sidorov
mayton
Код: java
1.
                    field.setAccessible(true);

Я бы сказал, что это - на помойку.
Вне зависимости от "доброты" ваших намерений.

если этот код работает вне спринга согласен,а если в спринге- то там так или иначе это все уже есть- поэтому тут или крестик надеть или трусы снять
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40133817
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По всем итераторам будет фикс.

Сейчас вот еще одна идея.


Код: java
1.
2.
3.
    public static <T> Stream<T> toStream(XMLStreamReader xmlStreamReader, Class<T> clazz) {
        return Stream.empty();
    }



Есть толстый XML. Намного больше памяти. И его надо поточно обрабатывать и получать некий стрим сущностей.
Здесь возможно еще не хватает третьего аргумента. Типа XPath expression но я над этим думаю как над опцией.

Сделаю идею - опубликую.

Попытки парсить такой файл через XmlDocument или через его неявное создание другими Xml средствами обычно
переполняют память. Я вот думаю об эконом-режиме.

Если кто знает уже такие готовые решения - плиз дайте ссылки.
...
Рейтинг: 0 / 0
Хозяйке на заметку
    #40133824
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу неправильной обёртки над ResultSet.

Есть ResulsSetIterator который уже почти всё делает что нам надо.

https://commons.apache.org/proper/commons-dbutils/apidocs/org/apache/commons/dbutils/ResultSetIterator.html

Вобщем мой сниппет можно выкинуть. Берите commons-dbutils.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Хозяйке на заметку
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]