четверг, 14 февраля 2013 г.

Отмена запроса PostgreSQL

Если программа вызовит долговыполняющийся запрос к PostgreSQL, то даже её закрытие не прекратит выполнение этого запроса. Особенно это актуально для REINDEX или FULL VACUUM, которые кроме того что долго выполняются, еще и блокируют таблицу.
Для отметы такого запроса, нужно вызвать другой запрос:
SELECT pg_cancel_backend(procpid) as x 
FROM pg_stat_activity 
WHERE current_query like 'REINDEX%';

среда, 13 февраля 2013 г.

WMI на C#

WMI (Windows Management Instrumentation) - это одна из базовых технологий для централизованного управления и слежения за работой различных частей компьютерной инфраструктуры под управлением платформы Windows. (Википедия)

Для работы с WMI Framework .NET предоставляет сборку System.Management.dll и одноименным неймспейсом.

Работа с WMI начинается с класса ManagementScope, который предназначен для подключению к серверу WMI, как локального компьютера, так и удаленного. Основной конструктор этого класса принимает 2 параметра:
  1. path - путь для подключения;
  2. options - параметры подключения.
Параметр path обычно: string.Format(@"\\{0}\root\cimv2", host). Пусть содержит хост компьютера к которому нужно подключиться, и путь неймспейса WMI (имеет иерархическую структуру). Имеется много нейсмпейсов, но наиболее используемый cimv2.
Параметр options содержит следующие поля:
  • Username - имя пользователя Windows.
  • Password/SecurePassword - пароль пользователя Windows.
  • Другия параметы - не использовал.
После создания объекта, для того чтобы подключения к WMI нужно вызвать метод Connect.
Исходный код подключения к WMI:
ConnectionOptions options = new ConnectionOptions();
options.Username = username;
options.Password = password;
scope = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", host),
    options);
scope.Connect();
Свойство IsConnected возвращает состояние подключения.
Важно: класс ManagementScope не имеет метода для разрыва связи, для того чтобы переподключиться, ножно повторно вызвать метод Connect.

После создания подключения, мы можем начать запрашивать различную информацию от WMI.
Для этого существует класс SelectQuery. В конструкторе ему передается строка с SQL-подобным запросом. После этого мы можем использовать объект класса SelectQuery для передачи его в конструктор класса ManagementObjectSearcher.

SelectQuery query = new SelectQuery(@"Select
    DeviceID, FreeSpace, Size, DriveType from Win32_LogicalDisk");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,
    query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject mo in queryCollection) {
    Console.WriteLine("DeviceID: {0}", mo["DeviceID"]);
    Console.WriteLine("FreeSpace: {0}", mo["FreeSpace"]);
    Console.WriteLine("Size: {0}", mo["Size"]);
    Console.WriteLine("DriveType : {0}", mo["DriveType "]);
}

Таким вот нехитрым способом можно получить с компа очень много системной информации.

понедельник, 11 февраля 2013 г.

JavaScript: объект select

Как известно объект select представляет собой выпадающий список. Он содержит список параметров (который и выпадает при нажании на него), доступ к которому можно получить через свойство options. Количество элеменов можно получить из свойства length самого объекта select. Свойство же size возыращает и задает количество отображаемых на странице элементов (не в выпадающем списке, а именно на странице). Я тестил это свойство в Chrome и при заничении size > 1 отображались все элементы списка.

Если необходимо чтобы список поддерживал множествнное выделение нужно присвоить свойсту multiple значение true.

Индекс текущего выбранного элемента содержится в свойстве selectedIndex. Если выбран режим со множественным выдылением, то это свойство содержит индекс первого выделенного элемента.

Так же имеется свойство form, которое ссылается на форму, в которой находится объект select.

Вставить новый элемент в список можно как с помощъю метода add самого select'a, так и с помощью метода add свойсва options.
selectObject.add(option,before)

Удаляются элементы списка методом remove:
selectObject.remove(index)

Также стоит напомнить как оформляеся select в HTML:


PS: подробная информация с примерами об объекте select находится сдесь.

пятница, 8 февраля 2013 г.

OpenSource: JSIL - компилятор C# в JS

Нашел в инете 3 основный проека по компилированию C# в JS:
Script# я тестил давно, мне не понравился :-) Не доделанный какой-то.
Про SharpKit пишут хорошие отзывы, но он платный.
А вот с JSIL можно поэксперементоровать. Он OpenSource и генерит вполне читаемый и логичный JS. На сайте есть возможность в онлайне скомпилировать любой код и увадеть что получится.
Написано что JSIL позволяет компилировать XNA игры и приведено нескольно демок. Но это надо еще проверить... У меня есть одна простая игра на XNA, будет время попробую скомпилировать.

Доступ к PostgreSQL через сеть

По умолчанию БД PostgreSQL настроина на доступ к ней только локально. Для того чтобы сделать доступной БД по сети нужно изменить настройку host в файле pg_hba.conf в каталоге БД. По умолчанию там стоит:
host    all             all             127.0.0.1/32            md5
Для того чтобы к БД можно подключиться в любого IP, намените эту настройку на следующую:
host    all             all             0.0.0.0/0            md5
или укажите нужную вам масту подсети.

среда, 14 ноября 2012 г.

Компоненты Visual Studio. Создание собственного редактора свойства

При написании своих собственных компонентов для Visual Studio часто возникает необходимость создать специальный редактор для свойств, значениями которых являются например объекты, неизвестный системе. Сделать свой собственный редактор свойства довольно просто.
Любой редактор свойства является классом унаследованным от UITypeEditor. Настройка поведения своего редактора свойства осуществляется путем переопределения предоставляемых этим классом виртуальных методов. UITypeEditor содержит следующие методы, предназначенные для переопределения:
  • EditValue – этот метод вызывается при начале редактирования свойства, в нем должен вызываться редактор, в результате возвращает полученное от редактора значение;
  • GetEditStyle – должен возвращать значение enum'а. Допускаются следующие значения:
    • None – никакой кнопки выводиться не будет;
    • Modal – кнопка в виде многоточия (типа "Обзор"), указывающая на то что при нажатии на нее откроется диалог для редактирования значения свойства:
    • DropDown – кнопка в виде выпадающего списка, указывающая на то что при нажатии на нее появится небольшая формочка для редактирования:
  • GetPaintValueSupported – указывает, нужно ли будет рисовать маленький прямоугольник, перед значением свойства  в PropertyGird'е:
  • PaintValue – вызывается при необходимости перерисовки маленькой картинки перед значением свойства в PropertyGird'е.
Теперь подробнее о том как работает этот механизм. В самом простом случае нужно переопределить два метода:
1) GetEditStyle – для задания вида редактора. Например если нужно получить выпадающую форму для редактирования, нужно сделать так:
public override UITypeEditorEditStyle GetEditStyle(
    ITypeDescriptorContext context)
{
    return UITypeEditorEditStyle.DropDown;
}
2) EditValue – для открытия редактора. Метод имеет следующую сигнатуру:
public Object EditValue(
 ITypeDescriptorContext context,
 IServiceProvider provider,
 object value)
где
  • context – не знаю для чего используется:-);
  • provider – обеспечивает объект интерфейса IWindowsFormsEditorService (путем вызова метода GetService(typeof(IWindowsFormsEditorService))). Этот объект предоставляет методы для отображения (DropDownControl) и закрытия (CloseDropDown) всплывающей формы редактора и метод ShowDialog для отображения диалога редактора.
  • value – текущее значение свойства.
Возвращает новое значение свойства, после изменения его в редакторе. Таким образом, переопределение метода EditValue должно выглядеть примерно так:
public override object EditValue(ITypeDescriptorContext context,
    IServiceProvider provider, object value)
{
    IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)
             provider.GetService(typeof(IWindowsFormsEditorService));
    if (edSvc != null)
    {
        MyEditorControl control = new MyEditorControl();
        control.Value = (MyEditableType)value;
        edSvc.DropDownControl(control);
        value = control.Value;
    }
    return value;
}
В коде можно увидеть использование неизвестного класса MyEditorControl. Этот класс и есть форма нашего редактора. Он является наследником класса UserControl (но может быть унаследован и от другого контрола). Реализация класса MyEditorControl должна иметь примерно следующий вид:
class MyEditorControl : UserControl {
    public MyEditableType Value {
        get; set;
    }
    //
}
Так как MyEditorControl является обычным контролом, вы можете пользоваться всеми средствами предоставляемыми Windows.Forms: создавать на нем кнопки, выпадающие списки, переопределять виртуальные методы (OnPaint, OnMouseDown, ...) и др.
Но это еще не все. В приведенном выше коде в качестве типа редактируемого свойства используется класс (или структура) MyEditableType. Этот тип является пользовательским и компонентная модель ничего не знает о нем. Для того чтобы объяснить компонентной модели как обращаться с этим типом, для него необходимо задать атрибут TypeConverterAttribute. В качестве параметра этот атрибут принимает тип класса, унаследованного от TypeConverter.

Исходный код в котором вы сможете увидеть применение редакторов свойств на практике можно найти здесь.

Игра на Java под Swing

Сейчас занимаюсь разработкой игры на Java, ориентируясь на Android, но ядро платформонезависимо. Поэтому для отладки использую Desktop версию. В Desktop версии графику реализовал через Swing. Для простоты в качестве элементов управления использую стандартные компонеты Swing. Для отрисовки графики испольую компонет Canvas.

Компонент Canvas
Унаследован от класса Component, специально предназначен для отрисовки на нем графики. На самом деле ничего особенного он из себя не представляет (убедиться можно посмотрев его исходный код). Он скорее своим названием декларирует что на нем будут рисовать. 
Класс предоставляет для переопределения метод paint(Graphics g), который выполняется при необходимости перерисовки.
Класс также предоставляет методы для использования двойной буфферизации (ДБ):  createBufferStrategy(int numBuffers) и getBufferStrategy().
Метод createBufferStrategy создает numBuffers буфферов. После его вызова можно использовать getBufferStrategy для получения объекта класса BufferStrategy, который предоставляет доступ к ДБ. Он имеет следующие важные методы:
  • getDrawGraphics() -- возвращает объект класса Graphics, на котором нужно рисовать.
  • show() -- отображает нарисованную в буфере картинку на экран (на компонент).
Т. е. для того чтобы отрисовать что-либо с использованием ДБ, нужно сделать следующее:
Canvas canv = new Canvas();
canv.createBufferStrategy(2);
Graphics g = canv.getDrawGraphics();
g.setColor(Color.RED);
g.drawRect(10, 10, 100, 100);
...
Цветофильтр
В игре используется цветовой фильтр для изменения цвета объектов (спрайтов). AWT предоставляет несколько способов для фильтрации (вродебы), я же использую класс RGBImageFilter. Он абстрактный и имеет абстрактный метод filterRGB(int x, int y, int rgb), который и нужно реализовать для наложения фильтра. Он должен возвращать цвет (int) пиксела в позиции (x, y). Параметр rgb -- исходный цвет пиксела. Чтобы применить этот фильтр к нужной картинке (Image), нужно сделать так:

FilteredImageSource filteredSrc = new FilteredImageSource(img.getSource(), filter);
Image filteredImage =  Toolkit.getDefaultToolkit().createImage(filteredSrc);

где, filter - это созданный ранее объект класса RGBImageFilter.

Доступ к ресурсам
Java позволяет хранить файлы различных типов непосредсвенно в jar файле. Для доступа к ним существует метод getClass().getResourceAsStream(name), где name -- путь к файлу ресурса. Путь включает /имя_файла.расширение. Имена пакетов разделяются символом /.
Например если вы поместили ваш файл empty.png в пакет com.yourname.resources.images, то путь к нему будет /com/yourname/resources/images/empty.png.
Метод возвращает поток для чтения (InputStream), далее с помощью ImageIO.read(inputStream) можно считать файл картинки в память.

Настройки пользователя
Для того чтобы хранить настройки и сохранения игры в папке пользователя создается подпапка ".название_гры". Получить путь к папке пользователя можно так:

System.getProperty("user.home");


Хранение данных
Данные храню в XML-файлах. Например карты хранятся в ресурсах в подкаталоге worlds. Их содержимое загружается в патмять с помощью сериализации. Для этого используется библиотека simple-xml. Она позволяет сериализировать и десериализировать объекты в стиле .NET (см. пост Сериализация в C#).

Кое-что
На Java я раньше не писал и игры не писал тоже (кроме простейшей игрухи на XNA). Поэтому в ходе работы я узнавал и понимал кое-что новое:
  • Картинки нужно кешировать. В игре используется разворот картинок, наложение фильтров и масштабирование. Все эти операции нагружают процессор. И когда я запустил игру (без кеширования), то заметил насколько сильно. 
  • Ну очевидно что нужно использовать ДБ, без нее никак.
  • При проектировании нужно максимально отделять логику игры от её графики.
  • Отрисовка графики тоже имеет логику) и нужно максимально отделить платформозависимую её часть от общей. Например класс Color является частью библиотеки AWT, и его не слудует использоват в ядре (движке) игры. Потом все равно придется переделывать чтобы заработало под Android.
Пожалуйста, оставляйте комментарии)