Общее·количество·просмотров·страницы

Java Dev Notes - разработка на Java (а также на JavaScript/Python/Flex и др), факты, события из АйТи

среда, 31 марта 2010 г.

Флеш-куки

Помимо HTTP-куков можно трекать посетителе сайта с помощью флеш-куков. Флеш-куки устанавливаются с помощью объекта flash.net.SharedObject. Физически флеш-куки хранятся в каталоге с настройками флеша. Например, на Windows XP этот каталог таков:

C:\Documents and Settings\Ivan\Application Data\Macromedia\Flash Player\#SharedObjects

UPD:

Website Privacy Settings panel - по этой ссылки можно редактировать настройки флеш-параметров для сайтов.

вторник, 30 марта 2010 г.

Обратное геокодирование на Google Maps, получение региона

Понадобилось мне как-то получить регион для множества гео-объектов. У меня есть координаты точек, и более ничего. А хочется для каждого гео-объекта иметь следующее: Страну-Регион-Субрегион. После этого я смогу, например, делать кластеризацию по регионам.

Пример данных вида Страна-Регион-Субрегион: Россия-Ленинградская область-Всеволожский район. Или: Россия-город Санкт-Петербург-Фрунзенский район.

Получение адреса (хотя бы приблизительного) объекта по его географическим координатам называется обратным геокодированием. В разделе Геокодирование можно почитать о том, что это такое, и как этим пользоваться в Google Maps.

Обратное геокодирование в Google Maps выполняется следующим образом: передается запрос вида

http://maps.google.com/maps/geo?q=60.6462623161,29.7290039063&output=xml&oe=utf8

Он возвращает информацию об адресе объекта с координатами (60.6462623161,29.7290039063), формат возвращаемых данных XML (т.е. KML). Можно еще получать данные в CSV, JSON. Информация об адресе содержится в xml-контейнерах Placemark. Этих контейнеров обычно бывает несколько в XML-документе. Каждый из них содержит информацию о ближайшей к объекту точке и ее адресе. В Placemark есть контейнер AddressDetails с атрибутом Accuracy. Если Accuracy=1, то в данном плейсмарке определена только страна, если Accuracy=2, то определена страна и регион, а если Accuracy=3, то дополнительно определен и субрегион. На большие значения Accuracy я не заглядывал, т.к. значения 3 мне хватало для моих целей за глаза и за уши.

Итак, у нас есть KML-документ, теперь мы его будем парсить. Парсер написан на Python.
Сначала нам потребуются две дополнительные функции: для извлечения текста из XML-ноды, а также для получения первого дочернего элемента. Вот эти функции:

def getFirstChildNode(parent,childNodeName):
choices = [e for e in parent.childNodes if e.nodeType == e.ELEMENT_NODE and e.nodeName == childNodeName]
for c in choices:
return c
return None
 
def getNodeText(node):
result = None
for c in node.childNodes:
if c.nodeType == Node.TEXT_NODE:
result = c.data
return result


Теперь представим всю функцию под названием getRegionFromKml:

def getRegionFromKml(kml):
kmldoc = minidom.parseString(kml)
 
result = {}
 
result['ok'] = False
 
result['CountryNameCode'] = None
result['CountryName'] = None
result['AdministrativeAreaName'] = None
result['SubAdministrativeAreaName'] = None
 
nodelist_status = kmldoc.getElementsByTagName("Status")
if len(nodelist_status)==0:
return result
node_status = nodelist_status[0]
node_code = getFirstChildNode(node_status,"code")
if not node_code: return result
code = getNodeText(node_code)
if not code == '200':
return result
 
nodelist_Placemark = kmldoc.getElementsByTagName("Placemark")
 
for node_Placemark in nodelist_Placemark:
if result['ok']:
break;
node_AddressDetails = getFirstChildNode(node_Placemark,"AddressDetails")
if not node_AddressDetails: continue
attribute_Accuracy = node_AddressDetails.getAttribute("Accuracy")
if not attribute_Accuracy: continue
accuracy = int(attribute_Accuracy)
if accuracy < 2: continue
node_Country = getFirstChildNode(node_AddressDetails,"Country")
if not node_Country: continue
 
node_CountryNameCode = getFirstChildNode(node_Country,"CountryNameCode")
if not node_CountryNameCode: continue
result['CountryNameCode'] = getNodeText(node_CountryNameCode)
#logging.info("country code: %s" %(result['CountryNameCode']) )
 
node_CountryName = getFirstChildNode(node_Country,"CountryName")
if not node_CountryName: continue
result['CountryName'] = getNodeText(node_CountryName)
 
#logging.info("CountryName: '%s'" % (CountryName))
node_AdministrativeArea = getFirstChildNode(node_Country,"AdministrativeArea")
if not node_AdministrativeArea: continue
 
node_AdministrativeAreaName = getFirstChildNode(node_AdministrativeArea,"AdministrativeAreaName")
if not node_AdministrativeAreaName: continue
result['AdministrativeAreaName'] = getNodeText(node_AdministrativeAreaName)
 
node_SubAdministrativeArea = getFirstChildNode(node_AdministrativeArea,"SubAdministrativeArea")
if node_SubAdministrativeArea:
node_SubAdministrativeAreaName = getFirstChildNode(node_SubAdministrativeArea,"SubAdministrativeAreaName")
if node_SubAdministrativeAreaName:
result['SubAdministrativeAreaName'] = getNodeText(node_SubAdministrativeAreaName)
 
node_Locality = getFirstChildNode(node_AdministrativeArea,"Locality")
if node_Locality:
node_LocalityName = getFirstChildNode(node_Locality,"LocalityName")
if node_LocalityName:
result['SubAdministrativeAreaName'] = getNodeText(node_LocalityName)
 
result['ok'] = True
 
return result
 


Для парсинга XML мы пользуемся пакетом minidom, так что в код нужно добавить пару импортов:

from xml.dom import minidom 
from xml.dom.minidom import Node


А вот как может выглядеть функция, которая а вход принимает широту и долготу, а на выход выдает объект, содержащий Страну/Регион/Субрегион данных координат:

def getRegionByLatLon(lat,lon):
result = {}
result['ok'] = False
 
try:
url = "http://maps.google.com/maps/geo?q=%10.8f,%10.8f&output=xml&oe=utf8" % (lat,lon)
urlResult = urlfetch.fetch(url)
 
if urlResult.status_code == 200:
kml = urlResult.content
result = getRegionFromKml(kml)
except:
logging.info('error occured when adding station: %s' % (sys.exc_info()[0]))
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
logging.error('exceptionType: %s' % exceptionType)
logging.error('exceptionValue: %s' % exceptionValue)
logging.error('exceptionTraceback: %s' % exceptionTraceback)
 
return result


Подробнее о парсинге XML на Питоне можно прочитать по следующим ссылкам:

xml.dom.minidom — Lightweight DOM implementation

Dive in Python - Chapter 5. XML Processing

Python & XML - Chapter 1

четверг, 25 марта 2010 г.

10 бесценных от Альберта Эйнштейна

Подробная версия лежит на Хабре: 10 бесценных жизненных советов, которые дает нам Альберт Эйнштейн.

Английская версия из блога DumbLittleMan: 10 Amazing Life Lessons You Can Learn From Albert Einstein.


  1. Будьте увлеченным
    У меня нет какого-то особого таланта. Я просто страсть как любопытен.

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

  3. Сфокусируйся на настоящем
    Любой мужчина, который может вести машину безопасно, пока целуется с симпатичной девушкой, попросту не уделяет поцелую должного внимания.

  4. Воображение могущественно
    Воображение это все. Оно способно показать нам заранее, как будут развиваться события. Воображение важнее знания.

  5. Совершайте ошибки
    Человек, который никогда не совершал ошибок, никогда не пробовал делать ничего нового.

  6. Живи настоящим
    Я никогда не думаю о будущем – оно наступает здесь и сейчас.

  7. Придавай значение
    Следует стремиться к тому, чтобы быть значимым, а не успешным.

  8. Не ждите разных результатов
    Это безумство делать одно и то же раз за разом, и при этом ждать разных результатов.

  9. Знание приходит из опыта
    Информация в чистом виде — это не знание. Настоящий источник данных это опыт.

  10. Поймите правила и побеждайте
    Вам следует выучить правила игры. И после этого вы будете играть как никто другой.

воскресенье, 21 марта 2010 г.

Чему я научился, собирая миллион долларов на стартап без бизнес-плана и финансовых прогнозов (потягивая при этом пиво)

Классный пост от Роберта Мэя: What I Learned Raising A Million Dollars For a Startup With No Business Plan and No Financial Projections (While Drinking a Beer). А на сайту StartupPoint находится его перевод. Очень и очень познавательно.

Вывод, впрочем, все тот же - нужно делать свой проект несмотря ни на что: несмотря на отсутствие инвесторов, отсутствие денег, присутствие многих других проблем, и т. д. Потому что вы и есть тот человек, которому этот проект нужен больше всего. Если вы от него откажетесь, то его не поднимет никто. Делать, делать, делать!

четверг, 4 марта 2010 г.

Генерация GUID на JavaScript

Как сгенерировать GUIDна JavaScript:

Способ номер раз (JavaScript GUID generator):

function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function guid() {
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}


Способ номер два (by StackOverflow How to create a GUID / UUID in Javascript):

function createUUID() {
// http://www.ietf.org/rfc/rfc4122.txt
var s = [];
var hexDigits = "0123456789ABCDEF";
for (var i = 0; i < 32; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
 
var uuid = s.join("");
return uuid;
}


One-liner solution (все с того же поста на StackOverflow):

'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
}).toUpperCase();


Здесь находится мемо, которое затем стало RFC4122: A Universally Unique IDentifier (UUID) URN Namespace

Robert Kieffer опубликовал файл Math.uuid.js, который содержит две реализации генератора UUID: RFC 4122 (функция Math.uuid) и более компактную RFC4122v4 (функция Math.uuid2). Ниже привожу исходник:

/*!
Math.uuid.js (v1.4)
http://www.broofa.com
mailto:robert@broofa.com
 
Copyright (c) 2009 Robert Kieffer
Dual licensed under the MIT and GPL licenses.
*/

 
/*
* Generate a random uuid.
*
* USAGE: Math.uuid(length, radix)
* length - the desired number of characters
* radix - the number of allowable values for each character.
*
* EXAMPLES:
* // No arguments - returns RFC4122, version 4 ID
* >>> Math.uuid()
* "92329D39-6F5C-4520-ABFC-AAB64544E172"
*
* // One argument - returns ID of the specified length
* >>> Math.uuid(15) // 15 character ID (default base=62)
* "VcydxgltxrVZSTV"
*
* // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
* >>> Math.uuid(8, 2) // 8 character ID (base=2)
* "01001010"
* >>> Math.uuid(8, 10) // 8 character ID (base=10)
* "47473046"
* >>> Math.uuid(8, 16) // 8 character ID (base=16)
* "098F4D35"
*/

Math.uuid = (function() {
// Private array of chars to use
var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
 
return function (len, radix) {
var chars = CHARS, uuid = [];
radix = radix || chars.length;
 
if (len) {
// Compact form
for (var i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
} else {
// rfc4122, version 4 form
var r;
 
// rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
 
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (var i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random()*16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
}
 
return uuid.join('');
};
})();
 
// A more compact, but less performant, RFC4122v4 compliant solution:
Math.uuid2 = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
}).toUpperCase();
};


Остальные реализации генератора GUID на JavaScript можно найти в уже упоминавшемся топике How to create a GUID / UUID in Javascript на StackOverflow.

Постоянные читатели