-Поиск по дневнику

Поиск сообщений в eugene20237

 -Подписка по e-mail

 

Проблемы современных GUI редакторов

Дневник

Воскресенье, 25 Сентября 2016 г. 16:06 + в цитатник
Вот вам мой меморандум: я считаю, что редактирование GUI в виде текста (xml почти во всех современных технологиях) - это плохая, неправильная идея. Когда редактируешь исходный текст нужно представлять в своем воображении графический образ интерфейса и постоянно строить связи между ним и xml. В итоге получается бессмысленная трата умственной энергии. Всё тоже самое относится к построению интерфейса через выполняемый код.

Нам уже давно доступны разнообразные возможности для визуального представления информации. Я думаю, что все скатываются к текстовому представлению, не из-за удобства, а по привычке. Я имею в виду не только наличие WYSIWYG-редакторов, но и любые другие современные средства редактирования: например, диалоги выбора шрифтов, диалоги выбора цвета... Вот таких средств сейчас пока очень мало создано для редактирования GUI, на мой взгляд.

Метки:  

Особенности LiqPay API

Дневник

Понедельник, 13 Января 2014 г. 00:39 + в цитатник
На мой взгляд, LiqPay API - это худший API платёжной системы с которым мне когда-либо приходилось работать. Сейчас я просто сделаю для себя пару заметок, чтобы вспомнить их, когда нужно будет снова где-то реализовывать поддержку LiqPay API.
1. Если при проведении платежа LiqPay API возвращает status=failure, но при этом оставляет поле code пустым, то скорее всего карта клиента не поддерживается этой системой или на ней не достаточно денег.
2. Если в result_url или server_url присутствует символ амперсанта "&", то такой XML не будет валидным с точки зрения LiqPay API.
3. result_url вызывается всегда ПЕРЕД server_url и содержит те же самые параметры. При этом server_url будет вызван только если в result_url пришел запрос с полем status=wait_secure.
4. LiqPay работает только с русскими и украинскими картами, ибо использует Приват-Банк.
5. LiqPay работает далеко не со всеми русскими картами стандарта MasterCard. Например, у меня он отказался работать с картой Яндекса без объяснения причин.
Просто чтобы не забыть.

Метки:  

Многострочные литералы в Java 6

Дневник

Понедельник, 10 Июня 2013 г. 17:29 + в цитатник
Через анотации:
http://www.adrianwalker.org/2011/12/java-multiline-string.html
Можно забацать анотацию в классе и запихнуть туда многострочный текст. Потом этот текст можно читать через попу.
Теперь я могу устроить революцию и свергнуть Spring!

А вот тут есть ещё один восхитительный хак:
http://blog.efftinge.de/2008/10/multi-line-string-literals-in-java.html
http://stackoverflow.com/questions/878573/java-multiline-string


// From:
// http://blog.efftinge.de/2008/10/multi-line-string-literals-in-java.html
// Takes a comment (/**/) and turns everything inside the comment to a string
// that is returned from S()
public static String S()
{
StackTraceElement element = new RuntimeException().getStackTrace()[1];
String name = element.getClassName().replace('.', '/') + ".java";
StringBuilder sb = new StringBuilder();
String line = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream in = classLoader.getResourceAsStream(name);
String s = convertStreamToString(in, element.getLineNumber());
return s.substring(s.indexOf("/*") + 2, s.indexOf("*/"));
}

// From http://www.kodejava.org/examples/266.html
private static String convertStreamToString(InputStream is, int lineNum)
{
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();

String line = null;
int i = 1;
try
{
while ((line = reader.readLine()) != null)
{
if (i++ >= lineNum)
{
sb.append(line + "\n");
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}

return sb.toString();
}

public static void main(String[] args) throws Exception
{
String s = S(/*
Wow, we finally have
multiline strings in
Java! HOOO!
*/);
System.out.println(s);
}

Метки:  

Концептуальные проблемы ООП

Дневник

Четверг, 09 Мая 2013 г. 00:35 + в цитатник
Проблема в том, что поведение объекта может зависеть от его внутреннего состояния. Да, это проблема! Приведу парочку примеров на Java о том, что я имею в виду.

Вот пример хорошего класса, поведение которого относительно независимо от состояния объекта:


class Simple
{
  private int a = 0;

  public void add(int b)
  {
    a = a + b;
  }

  public int getA()
  {
    return a;
  }
}


Здесь метод "add" работает одинаково независимо от значения свойства "a". А вот пример похожего класса, где метод "add" ведёт себя более изощрённо, ориентируясь на значение "a".


class Difficult
{
  private int a = 0;

  public void add(int b)
  {
    if ((float)(a % 100) / 3 == (int)((a % 100) / 3) )
      a = a + b;
    else
      a = a - b;
  }

  public int getA()
  {
    return a;
  }
}


Я специально придумал некое сложное условие, в зависимости от которого меняется поведение в методе "add". На практике могут быть множество флагов и других свойств объекта, которые влияют на поведение объекта, делая его настолько различным, что уместить это в голове уже становится сложно. Класс ориентируется на некоторые свойства, которые сам же и изменяет. Такие непредсказуемые классы неизбежно ведут к ошибкам.

Вот другой пример на языке AS3:


class D
{
  var param1: boolean;
  var param2: boolean;

  function func1(...)
  {
    .........
      if (param2)
        param1 = abc;
      else
        param1 = xyz;
    .........
  }

  function func2(...)
  {
    .........
    if (param1 && asd)
      param2 = ...;
    ...........
  }
}


Тут парочка булевых свойств, которые зависят друг от друга и влияют на поведение. Уже непросто объяснить что там происходит.

Вот такое наблюдение. Что с этим делать пока не знаю. Пойду ещё почитаю Фаулера.

Метки:  

Ещё одна полезность TODO списков и бумаги вообще

Дневник

Воскресенье, 07 Апреля 2013 г. 04:18 + в цитатник
20071126-todo-list (380x239, 202Kb)
Открыл для себя ещё одну сторону TODO списков. TODO списки на бумаге очень помогают! Когда в процессе работы возникают мелкие задачки типа: "проверить работу вот этой функции", можно записать это в TODO список и больше не хранить задачу в голове. Это реально очищает мозг! Такая практика позволяет мне концентрироваться на текущей задаче полностью и с удовольтствием. При этом не упускать ничего из виду.

Метки:  

Искусственная жизнь

Дневник

Воскресенье, 20 Мая 2012 г. 01:44 + в цитатник
В этом посте речь пойдёт о принципах построения искусственной жизни на основе ИИ, описанного ранее. Я обнаружил одну важную особенность: каждое действие неразрывно связано с состоянием, в котором его можно применять. Под состоянием (S) понимается все необходимые условия, в которых действие может быть исполнено. Т.е. в неоптимизированном идеальном варианте это совокупность всех параметров мира, в модели которого живёт ИИ. В оптимизированном варианте это только явно необходимые параметры без учета "погоды на Марсе".

Если ИИ нашёл новое сложносоставное действие с помощью анализа лога экспериментов, рассмотренного в предыдущем посте, то он обязан привязать это действие к набору параметров S, при которых оно может быть выполнено. Таким образом, к одному и тому же эффекту (состоянию), могут вести несколько действий, как примитивных, так и составных. Подходящее действие ИИ выбирает исходя из условий, в которых он находится.

Некоторые эффекты воздействий, которые являются целями ИИ, в течение его жизни, должны быть изначально прошиты, для того чтобы он обрёл цель после рождения и начал действовать. Другие эффекты он может сам обозначить целями в ходе движения к какому-то изначально прошитому эффекту.

Пусть A0 - множество всех действий прошитых в ИИ при рождении, а S - состояние системы. Тогда в общем виде алгоритм искусственной жизни будет выглядеть следующим образом.
PHP:

// необходимо достичь предустановленного эффекта S1
1.случайный_перебор_действий(A0S1)
// эффект S1 достигнут, а также найдены многие другие действия и сохранены в множество A1
// необходимо достичь предустановленного эффекта S2
2.случайный_перебор_действий(A0 A1S2)
// эффект S2 достигнут, а также найдены многие другие действия и сохранены в множество A2
// необходимо достичь предустановленного эффекта S1 и есть действие a75 для его достижения в условиях S75
3.случайный_перебор_действий(A0 A1 A2S75)
// достигнуты условия S75, теперь можно выполнять действия для достижения цели S1
4.выполнение_набора_действий(a75)
// эффект S1 достигнут, многие действия откорректированы
...
font>


На шаге 3 и 4 демонстрируется как ИИ выбирает промежуточный эффект S75 в качестве цели для достижения эффекта S1. Теперь о том, что такое случайный_перебор_действий(...) и как он может быть запрограммирован. Всё очень просто:
PHP:

случайный_перебор_действий
(Aмножество действийStцелевое состояние системы)
{
  
Ac найти_действия_приводящие_к_эффекту(ASt)
  
Ss извлечь_начальные_условия(Ac)
  while (
!= St && not(S in Ss))
  {
    
A0[random(LEN(A))]
    
выполнение_примитивного_действия(a)
  }
  if (
== St)
    return;
  if (
S in Ss)
  {
    
найти_действие_по_начальным_условиям(AcS)
    
выполнение_набора_действий(a)
    if (
== St)
      return;
    else
      exit(
"Критическая ошибка, обратитесь к разработчикам.");
  }
}
font>


Функция случайный_перебор_действий(...) всегда должна завершаться удачно, т.е. приводить к искомому эффекту St. Эта функция пытается найти промежуточные точки для перехода к состоянию St и далее перебирает примитивные действия до тех пор пока одна из этих точек не будет достигнута. Если таких точек не нашлось вовсе, эта функция будет делать перебор примитивных действий до тех пор пока не достигнуто условие St.

Конечно же это тоже не боевые условия и надо бы перебирать не примитивные действия, а составные, но с учётом времени их выполнения и адекватности ситуации. Кроме того, в реальных условиях надо учитывать вероятности появления того или иного эффекта при выборе действий. Всё это мы оставим на потом! В этом посте показан только принцип, по которому, на мой взгляд, можно строить искусственную жизнь с искусственным интеллектом.

Метки:  

ИИ: анализатор экспериментов

Дневник

Суббота, 19 Мая 2012 г. 22:00 + в цитатник
В этом посте я приведу очень простой пример предметной области и алгоритм анализатора экспериментов, указанного в схеме к прошлому посту. Вообще, лог экспериментов - это аналог последовательности команд на языке ассемблера. Поэтому в нём могут быть скрыты условные переходы и циклы за логикой примитивных операций. В данном посте я не рассматриваю варианты поиска циклов и условных переходов в логе экспериментов. Для упрощения понимания сути работы анализатора он будет искать одну единственную каноническую конструкцию - простую последовательность операций. Операция в данном случае означает действие ИИ на объект исследования, выполняемое в ходе эксперимента.

Предметная область
Существует единственный объект исследования, состояние которого описывается набором дискретных параметров. Каждый параметр представляет собой флаг, т.е. может принимать только значения 0 и 1. Для этого объекта допустимо несколько примитивных действий, каждое из которых определённым образом меняет состояние объекта. Изменение состояния объекта имеет внутреннюю логику и недоступно извне. Т.е. объект исследования является для нас "чёрным ящиком". Однако, каждое примитивное воздействие всегда оказывает однозначный простой эффект. Кроме того, существует несколько фиксированных последовательностей команд, которые оказывают на объект новые эффекты. Эти эффекты меняют параметры состояния объекта отлично от примитивных действий.

Над объектом исследования проводится большое количество экспериментов, каждый из которых состоит в применении случайного примитивного действия к объекту и записи в лог его нового состояния.

Цель и задача
Анализатор просматривает лог экспериментов и пытается обнаружить все последовательности команд и новые эффекты, которые они оказывают на объект. Полученные наборы действий являются новыми стратегиями поведения ИИ, что есть результат его обучения. Требуется определить все эти наборы действий.

Модель данных
A - это множество примитивных действий, допустимых для объекта исследования.
A = { a1, ..., ax }.
C - это эксперименты, т.е. последовательность наших действий, применяемых к объекту.
C = { c1, ..., cn }, где ci принадлежит множеству действий A.
S - состояние системы после каждого эксперимента. Каждое состояние объекта состоит из m флагов.
S = { s1, ..., sm }, где si может быть 0 или 1.

Если проанализировать последовательности C и S, то можно выявить удачные блоки, приводящие к новым эффектам на множестве S. E = { e1, ..., el } - это искомые последовательности действий, где ei принадлежит множеству команд A = { a1, ..., ax }.

Алгоритм анализа экспериментов
Для начала необходимо сопоставить каждому действию ci эффект, который оно оказывает на объект исследования. Эффект воздействия - это изменение переменных состояния из множества S. Для того чтобы собрать эту информацию введём хранилище эффектов воздействий и обозначим его множеством D.
D = { d1, ..., dx }, где di = { ds1, ..., dsn };
Каждый эффект - это изменение параметров состояния объекта, которое хранится во множестве S и меняется после каждого эксперимента. Обозначим изменение каждого параметра из множества S структурой ds:
dsi = { S[i][j-1], S[i][j] }.
Как видно из формулы, эта структура хранит два состояния параметра S[i] - до эксперимента под номером j и после. Здесь j - номер эксперимента, который лежит в интервале от 1 до n.
Для построения множества D можно использовать следующий простой алгоритм.
PHP:

2
while (j<=&& LEN(D) < x)
{
  
C[j]
  
A[c]
  if (
D[a] == NULL)
  {
    
= {}
    for (
i=1i<=mi++)
    {
      
ds = { S[i][j-1], S[i][j] }
      
d[i] = ds
    
}
    
D[a] = 
  
}
  
j++
}
font>


Этот алгоритм будет правильно работать при условии, что каждое примитивное воздействие всегда оказывает однозначный простой эффект. Это указано в описании предметной области. Если же эффект от примитивного воздействия будет разным, то потребуется учитывать также вероятности этих эффектов в дополнение к множеству D. В этом посте я ограничусь описанием самого простого случая.

Теперь можно анализировать весь лог экспериментов C, чтобы найти в нём последовательности действий приводящие к неожиданным эффектам. Для этого предлагается просматривать лог до появления неожиданного изменения состояния и когда оно будет замечено, сохранить несколько предыдущих экспериментов, привязав их к этому эффекту. В данном случае мы будем запоминать 10 предыдущих экспериментов в список T. Далее продолжаем просматривать лог C и при обнаружении уже запомненного эффекта добавляем ему в соответствие новые 10 предыдущих экспериментов. Делаем так до тех пор, пока для каждого эффекта не накопится достаточно количество появлений и соответствующих экспериментов. В данном случае мы ограничимся 3-мя появлениями каждого эффекта. Три эффекта будем считать уже закономерностью. Теперь для каждого эффекта сравниваем группы экспериментов и, если среди них есть одинаковые последовательности команд, добавляем эти команды в искомое множество E. В целом, псевдокод алгоритма построения множества E выглядит следующим образом.
PHP:

= {} // список неожиданных эффектов
1
while (j<=n// анализируем эксперименты
{
  
C[j]
  
A[c]
  
= {}
  for (
i=1i<=mi++) // формируем d
  
{
    
ds = { S[i][j-1], S[i][j] }
    
d[i] = ds
  
}

  if (
D[a] != d// неожиданный эффект
  
{
    
// запоминаем эффект в другой переменной
    
= []
    
j
    
while (i>=&& i>=j-10// находим 10 предыдущих действий
    
{
      
C[i]
      
A[c]
      
= {}
      for (
k=1k<=mk++) // формируем d
      
{
        
ds = { S[k][i-1], S[k][i] }
        
d[i] = ds
      
}
      
// запоминаем в список t действие a и его эффект d
      
t[LEN(t) + 1] = { a}
      
i--
    }
    
// сохраняем 10 предыдущих действий для эффекта f
    
T[f][LEN(T[f]) + 1] = t
  
}
  
j++
}

// формируем множество E
for (fZin T // f - ключ, Z - значение в коллекции T
{
  if (
LEN(Z) >= 3// является ли это закономерностью?
  
{
    
= [] // элемент искомого множества E
    
Z[1// эталонный образец последовательности, приводящей к эффекту f
    // ищем, где заканчивается одинаковая последовательность действий
    
for (j=2j<=LEN(Z); j++)
    {
      
Z[j]
      
LEN(t)
      do
      {
        
t[i].// действие
        
t[i].// изменение состояния
        
if (== o[i].&& == o[i].d)
        {
          if (
e[LEN(e) + 1] == NULL)
            
e[LEN(e) + 1] = a
        
}
        else
          break
        
i++
      }
      while(
<= LEN(t))
    }
    
E[f] = // добавляем новую стратегию в множество E по ключу f
  
}
}
font>


Вот и всё, множество E построено. Оно содержит последовательности действий, которые приводят новым эффектам. Обратите внимание, что множество E представлено в псевдокоде ассоциативным массивом. В этом массиве каждому ключу f (сам эффект) сопоставлены последовательности действий из множества A, которые приводят к этому эффекту. Таким образом, элементы из множества E можно использовать в качестве новых, теперь уже составных, действий. Эти составные действия можно применять к объекту исследования чтобы добиться какого-либо эффекта f.

Прошу понять, что данный псевдокод может содержать мелкие логические ошибки и в целом я не делал такой реализации. Всё это лишь алгоритмические выкладки, которые являются основой для дальнейшего исследования и совершенствования ИИ. Это именно основа, база, потому что рассмотренная предметная область очень проста и не соответствует реальным задачам. Однако этот пример позволяет понять принцип работы анализатора экспериментов и генерации новых стратегий для ИИ.

Если Вы нашли логические ошибки в псевдокоде или у Вас есть другие ценные мысли по ИИ, прошу писать в комментарии. Спасибо.

Метки:  

Многоагентное программирование

Дневник

Суббота, 19 Мая 2012 г. 04:35 + в цитатник
Вот подумалось, так что мысли сырые. А что если изобрести такой стиль программирования, где все объекты жили бы в реальном времени и обменивались сообщениями? Представьте себе стратежку типа Старкрафта. В ней юниты и здания - это программные объекты, которые друг с другом взаимодействуют и в итоге чего там строют. Так вот, если программные объекты представить в виде таких же юнитов, то для них можно будет писать функции жизни, а не реакции на события, как в традиционном ООП. Т.е. представлять себе процесс не виде алгоритма, а в виде взаимодействий объектов, как в реальной жизни.

В традиционном ООП есть корневой объект, который создает другие. Те в свою очередь создают ещё более другие и т.д. В предлагаемом подходе нет никаких внешних контролирующих алгоритмов. Это должна делать виртуальная машина, которая ведёт себя аналогично какой-нибудь стратежке, но с более широкими возможностями программирования юинтов-объектов.

Было бы интересно. Просто для фана, поиграться. А потом, глядишь, и выйдет чего.

UPDATE: всё это называется многоагентными системами. Программировать в них можно вот так например.

Метки:  

Hello World в подарок программисту

Дневник

Пятница, 09 Марта 2012 г. 01:00 + в цитатник
Моя девушка решила меня порадовать и написала Hello World. Так приятно это!

<input type="button" value=" Нажми меня " ONCLICK="AlertButton()" >
<script>
function AlertButton()
{
window.alert("Hello, World!");
}
</script>

Метки:  

FDT мегасетап

Дневник

Четверг, 29 Декабря 2011 г. 08:58 + в цитатник
Пару дней ковырялся чтобы настроить IDE для серверной и клиентской части одного проекта. Захотелось мне заставить IDE одновременно работать как серверной так и с клиентской частью чтобы не тратить внимание на переключение между разными средами. Сложность в том, что клиент и сервер на разных языках, соответственно на Флеше и на Питоне. И вот наконец получилось!

В качестве основы взял среду FDT4, потому что она быстрая и на ней уже работает Флеш. Установил в неё PyDev и кучу разных плагинов, в т.ч. для синхронизации с удалёнными серверами. Серверную часть пока запускаю на той же машине, что и клиентскую, но ничто не мешает и править серверный код удаленно потому что есть RSE для Эклипса. Отдельная проблема была с FlashPlayer, потому что для юнит-тестов он совершенно не нужен и его окошко надо было спрятать. Как это сделать нормально пока не знаю, может быть надо писать тесты на Adobe AIR. Я же извратился и вызываю плеер через браузер в одной и той же вкладке, а само окно браузера скрыл навсегда сторонней утилиткой. В результате у меня получилась IDE с двумя консолями и двумя проектами, где ничто не отвлекает от сути.

FDT_setup (700x526, 249Kb)

Метки:  

Картиночка для программистов

Дневник

Пятница, 08 Апреля 2011 г. 18:59 + в цитатник
Специально для коллег, сделал такую вот картиночку:

for_amage (400x400, 199Kb)

Метки:  

Away3D 4.0 public beta now available!

Дневник

Понедельник, 28 Февраля 2011 г. 15:43 + в цитатник
Свершилось!!!
Away3D 4.0 public beta now available! (see away3d.com)
Руки чешуться попробывать! Теперь он поддерживает Molehill 3D API.

Для тех кто в танке:
В воскресенье, 27 февраля 2011 года, компания Adobe открыла доступ к бета-версии Molehill 3D API для Flash Player 11. Данная технология задействует для обработки изображения графический процессор видеокарты, позволяя добиться высококачественной современной графики в браузерных приложениях. Скачать первые публичные сборки (билды), документацию и набор инструментов Flex SDK можно с сайта labs.adobe.com из раздела AIR and Flash Player Incubator.
 (600x211, 175Kb)

Метки:  

Mutable код

Дневник

Четверг, 14 Октября 2010 г. 21:04 + в цитатник
Частенько ко мне в голову лезет мысль о том, что хорошо бы сделать заменитель капчи на основе мутируемого кода. Т.е. нажимаем кнопочку на js или флеше, которая выполняет некий код, формирующий дополнительные параметры. Такое уже много где есть, но код этот можно один раз расшифровать и делать бота. Смысл в том чтобы этот код был каждый раз разным, т.е. менялся в зависимости от каких-нибудь параметров, которые можно задавать случайным образом. По сути это обфускатор с широкими возможностями.

Это всё не спасёт, если бот работает с браузером и сам двигает мышку, но от парсинга исходников защитит на 100%.

Метки:  

Стихии в программировании

Дневник

Вторник, 27 Июля 2010 г. 21:43 + в цитатник
Спустя несколько лет пришёл к выводу, что в процессе программирования можно выделить несколько тактик, которые можно сравнить со стихиями.

1. Стихия Земли. Фундаментальное железобетонное программирование. Каждый блок код кода идеально структурирован и программист от него не отрывается, пока у него не возникнет чувство идеального творения. Каждый фрагмент программы настолько хорошо структурирован с точки зрения программиста, что похож на железобетонную крепость, которой не страшны баги и задачи. Всё это похоже на стихию Земли.
2. Стихия Огня. Иногда надо сделать что-то быстро и выстраивать стены нет времени. Предпочтение отдаётся нестандартным идеям позволяющим сделать сложную программу быстро. Очень часто такой тип программирования превращается в полный хаос, когда из-за отсутствия всяких правил становится уже ничего непонятно и программа заходит в тупик. Однако при разумном балансе многие допущения вызывают ощущение одержимости - получается много и сразу. Это очень похоже на огонь.

Других стихий пока почувствовать не удалось. Наверное они тоже есть.

Метки:  

 Страницы: [1]