Русские субтитры: Ёжификатор для Subtitle Workshop - Русские субтитры

Перейти к содержимому

  • (2 Страниц)
  • +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

Ёжификатор для Subtitle Workshop

#21 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 16 Ноябрь 2007 - 11:49

Просмотр сообщенияD!ig (9.11.2007, 23:53) писал:

Хотел покрасить синтаксис, это несложно, но на один этот кусок ушло бы 100Кб :mad:


ну и хрен с ним :)
0

#22 Пользователь офлайн   НуПогоди Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Избранные
  • Сообщений: 832
  • Регистрация: 31 Июль 06
  • Страна:
  • Прислал(a) субтитров: 46
  • Своих переводов: 19

Отправлено 16 Ноябрь 2007 - 14:26

Поковырялся вчера в своём многострадальном скрипте: изыскивал ресурсы для оптимизации по скорости. Кое-что уже реализовал на скорую руку. Как доведу до ума - выложу... Но сперва интересно послушать ваше мнение: что устраивает, а что - нет?

Итак, есть 2 независимых процесса, которые нужно было оптимизировать.
  • Подготовительные процедуры: считывание словаря, его ежификация (ё>е) плюс "рассыпание" словаря по отдельным стрингам (по первой букве)
  • Непосредственно поиск и замена по тексту субтитров
С поиском я вроде окончательно разобрался. Учитывая, что словарь идёт в строго алфавитном порядке я устранил цикл поиска в стиле "до победного конца" (точнее, до 2х оставшихся букв) и теперь вызываю "медленную" функцию Pos по принципу "один Pos на одно слово". Скорость поиска увеличилась где-то вдвое. Дальше с ней возиться пока смысла не вижу...

Чуть хуже с подготовительными процедурами... В версии 0.03 они занимали около 7 секунд (на моём CPU). Меня это не слишком устаивало, поэтому вчера попытался изыскать самое проблематичное место. Как выяснилось, почти все 7 секунд занимает ежификация словаря: надо просканировать около миллиона букв, проверить и заменить все "ё" на "е". Поэтому сразу же появилась идея повторять эту процедуру не каждый раз, когда запускается скрипт, а только единожды. Пока сделал так, что при первом запуске скрипта сперва считывается Ё-словарь, из него создаётся Е-словарь (такой же точно файл, где все буквы "ё" заменены на "е") и записывается на диск (т.е. первый запуск - медленный, около 7 сек на подготовку). При втором и последующих запусках скрипт считывает оба словаря (и это по сравнению с первым запуском почти не требует времени на подготовку скрипта к работе). Вроде работает. Платить за скорость приходится 1МБ свободного места на диске, что в наши времена - не слишком большая проблема.

Прилагаю картинку с тестами... Подготовительные процедуры соответствуют контуперному времени при обработке 0 слов, а наклон кривых - это практически скорость поиска и замены. Все тесты естественно проводились в режиме автозамены, когда работу скрипта не тормозит пользователь (а стандартная программа YO.exe была к тому же выставлена в режим "быстрая промотка", когда текст на экране не скроллируется - самый быстрый вариант). Как по-вашему, стоит ли оно того? В смысле, стоит ли 1МБ места на диске "7-секундного" выигрыша? Я пока склоняюсь к мысли, что так сделать стоит. Но у каждого свои тараканы в голове... А если есть другие идеи как ускорить скрипт - you are welcome.

Прикрепленные файлы

  • Прикрепленный файл  Speed.png (44,18К)
    Количество загрузок:: 11

0

#23 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 16 Ноябрь 2007 - 20:39

Просмотр сообщенияНуПогоди (16.11.2007, 12:26) писал:

А если есть другие идеи как ускорить скрипт - you are welcome.


Последнюю версию скрипта на базу, тогда и будем говорить. :)
0

#24 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 17 Ноябрь 2007 - 05:19

Просмотр сообщенияНуПогоди (16.11.2007, 13:26) писал:

Но сперва интересно послушать ваше мнение: что устраивает, а что - нет?

Ради интереса запустил, вылезает сообщение "типа автоматом не заменить решай, что хочешь" и показывает строку титра, а по ней одной невозможно было определить, что надо Е или Ё. Скролить список титров нельзя, окно сообщения модальное.

Идея! А нафига тебе окно? Вставить панельку на место поля TEКСТ СУБТИТРА.
Грузить скрипт 1 раз, после завершения работы панельку скрыть. Перевесить обработчик пункту меню, для запуска скрипта, чтобы при повторном клике панелька делалась видимой. Круто будет B).

Просмотр сообщенияНуПогоди (16.11.2007, 13:26) писал:

Учитывая, что словарь идёт в строго алфавитном порядке я устранил цикл поиска в стиле "до победного конца" (точнее, до 2х оставшихся букв) и теперь вызываю "медленную" функцию Pos по принципу "один Pos на одно слово". Скорость поиска увеличилась где-то вдвое. Дальше с ней возиться пока смысла не вижу...

А может рассыпать все слова по массивам. YO[1..34].WORD[1..*], а слово искать бинарным поиском, правда опять вопрос разных словоформ.

Имхо Pos ищет циклом представляя строку как массив str[i] и каждый раз с начала.
Так что можно написать функцию PosEx c возможностью поиска от указанной позиции.

Скриптам доступна функция StrGet возвращает Char, смысла в ней не вижу вроде тоже что и str[i]. Но может можно этот Char превратить PChar, должна получится строка начинающаяся с указаной позиции, и являющаяся фрагментом полной строки, при этом копия не создастся. Но это так, мои мысли, эксперементов не проводил. Это, чтобы не обрезать строку.

Просмотр сообщенияНуПогоди (16.11.2007, 13:26) писал:

А если есть другие идеи как ускорить скрипт - you are welcome.

Давно хотел предложить, но так как мой пост в теме был последний, а дописывать к нему не хотелось, ничего и не предложил. :) Исправляюсь.
function IsYOEInside
var
 k			: Integer;
begin
result:=0;		
case REGIME of
1:	begin	// считает только «Е»
	for k:=1 to Length(src) do
		begin
		if((src[k]='е')or(src[k]='Е')) then 
		result:=result+1;
		end;
	end;
2:	begin	// считает и «Е» и «Ё»
	for k:=1 to Length(src) do
		begin
		if((src[k]='е')or(src[k]='ё')or(src[k]='Е')or(src[k]='Ё')) then 
		result:=result+1;
		end;
	end;
3: 	begin	// считает только «Ё» - это режим для маргиналов. 
	for k:=1 to Length(src) do
		begin
		if((src[k]='ё')or(src[k]='Ё')) then 
		result:=result+1;
		end;
	end;
end;

меняем на
var
 k			: Integer;
 length_src : Integer;
begin
result:=0;
Length_src:=Length(src);

  for k:=1 to Length(src) do	
  begin
	case REGIME of		
	1:	result:=result+byte((src[k]='е')or(src[k]='Е')); // считает только «Е»
	2:	result:=result+byte((src[k]='е')or(src[k]='ё')or(src[k]='Е')or(src[k]='Ё')); // считает и «Е» и «Ё»
	3: 	result:=result+byte((src[k]='ё')or(src[k]='Ё')); // считает только «Ё» - это режим для маргиналов.
	end;	
  end;

Так компактнее, про скорость не знаю. В принципе вообще в 1 строчку можно уписать.

function IsWordFound
while (Pos(s,dict2)=0) do Delete(s,Length(s),1);
// comment
j1:=Pos(s,dict2);

меняем на
repeat
  j1:=Pos(s,Dict2);
  if (j1=0) then Delete(s,Length(s),1);
until (j1<>0);

Экономим 1 вызов Pos.

	j1:=Pos(s,dict2);						// находим точку, где начинается слово	
	Delete(dict2,1,j1+1);					// отрезаем начало словаря E
	Delete(dict1,1,j1+1);					// отрезаем начало словаря YO
	j1:=Pos(CRLF,dict2);					// ищем в обрезанном словаре хвост строчки =CRLF
	Delete(dict2,j1,Length(dict2)-j1+1); 	// и обрезаем по нему оба словаря
	Delete(dict1,j1,Length(dict1)-j1+1);

меняем на
	k1 :=Length(dict2);
	j1:=j1+2;
	for n:=j1 to k1-1 do // ищем хвост строчки
	 if (dict2[n]=#13) {and (dict2[n+1]=#10)}
	  then break; 	
	dict2 := Copy(dict2, j1, (n-j1)); //отрезаем начало и конец словаря E
	dict1 := Copy(dict1, j1, (n-j1)); //отрезаем начало и конец словаря Yo

экономим на Pos - сделан в предыдущей оптимизации. И второй Pos - заменен просмотром массива от текущей позиции. Убраны 4 ужасных delete'а. Размеры Dict2 и Dict1 равны? Зачем делать 2 Length если достаточно 1го? Вроде этот кусок, тестил в Delphi, работает в 2,5-3 раза быстрее.

	  if (i1+j1)<>0 then Delete(dict2,Length(dict2)-i1-j1+1,i1+j1);

меняем на
	if (i1+j1)<>0 then dict2:=copy(dict2,1,k1-i1-j1);

Length(Dict2) не нужен 3 строками выше делался, и с тех пор Dict2 не менялся. Ну и Copy всяко лучше чем Delete (имхо :wacko:).

----
Но видать в моих оптимизациях, где-то, есть изъян. При безусловной замене твой вариант заменил 1 слово, мой 19 :oops: , всего можно было заменить 66. Проблема наверно с Copy, где-то неправильно определяются границы слова (+-1 символ).
0

#25 Пользователь офлайн   НуПогоди Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Избранные
  • Сообщений: 832
  • Регистрация: 31 Июль 06
  • Страна:
  • Прислал(a) субтитров: 46
  • Своих переводов: 19

Отправлено 19 Ноябрь 2007 - 13:03

Просмотр сообщенияBedaZzle (16.11.2007, 17:39) писал:

Последнюю версию скрипта на базу, тогда и будем говорить. :)
Выложил...

Просмотр сообщенияD!ig (17.11.2007, 2:19) писал:

Вроде этот кусок, тестил в Delphi, работает в 2,5-3 раза быстрее.
Да, ты прав, конечно... Но когда я писал о том, что "разобрался с поиском", я как раз эту функцию и имел в виду. Откорректировал я её приблизительно в том же стиле (убил все Delete, убрал несколько Pos - oставил только один-единственный). И выигрыш в скорости поиска получил где-то аналогичный. См. картинку с результатами тестов, я её чуть выше приаттачил (наклон кривых - это скорость поиска: версия 0.03 против версии 0.04).

Просмотр сообщенияD!ig (17.11.2007, 2:19) писал:

Ради интереса запустил, вылезает сообщение "типа автоматом не заменить решай, что хочешь" и показывает строку титра, а по ней одной невозможно было определить, что надо Е или Ё. Скролить список титров нельзя, окно сообщения модальное.

Идея! А нафига тебе окно? Вставить панельку на место поля TEКСТ СУБТИТРА.
Грузить скрипт 1 раз, после завершения работы панельку скрыть. Перевесить обработчик пункту меню, для запуска скрипта, чтобы при повторном клике панелька делалась видимой. Круто будет .
Подумаю... Если действительно бывают ситуации, когда из контекста саба неясно, писать ли слово через "е" или через "ё", то действительно надо чтой-то делать...
0

#26 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 19 Ноябрь 2007 - 14:55

Просмотр сообщенияНуПогоди (19.11.2007, 11:03) писал:

Подумаю... Если действительно бывают ситуации, когда из контекста саба неясно, писать ли слово через "е" или через "ё", то действительно надо чтой-то делать...


Показать окошко с парой предыдущих и парой последующих субтитров, вот и вся любовь.

Просмотр сообщенияНуПогоди (19.11.2007, 11:03) писал:

Выложил...


поправь даты выхода версий ;)
0

#27 Пользователь офлайн   НуПогоди Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Избранные
  • Сообщений: 832
  • Регистрация: 31 Июль 06
  • Страна:
  • Прислал(a) субтитров: 46
  • Своих переводов: 19

Отправлено 19 Ноябрь 2007 - 15:04

Просмотр сообщенияBedaZzle (19.11.2007, 11:49) писал:

Показать окошко с парой предыдущих и парой последующих субтитров, вот и вся любовь.

Можно и так... По крайней мере, это самое простое, что приходит на ум.

В свете последних откровений от D!ag у меня появилась идея сделать подсветку тех титров, где скрипт сделал поправки. До сих пор я обычно находил поправки через *опу: спасал файл с титрами, а потом сравнивал его с оригиналом в TotalCommander (выделял два файла, потом Files > Compare By Content...) Работает, но слишком хлопотно это... Только вот нужно будет разобраться во всех этих идиотских SW-панелях и написать маленькую функцию SetSubtitleColor(num,color) (типа стандартной SetSubtitleText(num,text)). Если найду время (у меня сейчас на работе лёгкий аврал) - этим прежде всего и займусь.

А что там с датами? Версии я пока выкладываю по понедельникам, сранья... Дата обычно стоит "вчерашняя", т.е. за воскресенье. Посмотрел: вроде всё с датами в порядке. АААААА! Месяц перепутал!
Бывает... Спасибо. Поправил...
0

#28 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 19 Ноябрь 2007 - 17:58

Просмотр сообщенияНуПогоди (19.11.2007, 13:04) писал:

В свете последних откровений от D!ag у меня появилась идея сделать подсветку тех титров, где скрипт сделал поправки.


можно русский текст загружать как оригинал, а в перевод лепить исправленный текст
воркшоп сам выделит различия, если это указано в настройках :)
0

#29 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 20 Ноябрь 2007 - 01:17

Цитата

А если есть другие идеи как ускорить скрипт - you are welcome.

Я, вот тут, глянул библиотеку FastCode (там в основном про строки). Там конечно много ассемблера, но также есть чисто паскалевые варианты функций, может удастся реализовать их в скрипте?
Оттуда можно украсть :):
UpperCase (LowerCase делается по аналогии). Идея там такова: сначала в функции Init???? создается массив (глобальная переменная) с заглавными.
Потом в самой функции UpperCase, циклом перебираются буквы в слове и мелкие заменяются на большие :). Плюс там что то еще хитрое с выравниванием команд.
» Нажмите, для отображения текста «

Copy (варианта там 2, но первый использует указатели, а скрипты указатели вроде не понимают)
PosEx (но тоже указатели использует)

Просмотр сообщенияНуПогоди (19.11.2007, 14:04) писал:

В свете последних откровений от D!ag

Вообще-то я D!ig, сокращенно от Indigo. Этот ник (Indigo)у меня появился, задолго до того как я оказался в инете. А как оказался, выяснилось, что в инете он сильно затаскан (на любом форуме 1 Indigo скорее всего есть). Сил придумывать, что-то оригинальное, у меня уже не было. Поэтому решил вот так сократится.

Просмотр сообщенияНуПогоди (19.11.2007, 14:04) писал:

появилась идея сделать подсветку тех титров, где скрипт сделал поправки.

Скорее всего не получится. Список титров имеет тип TVirtualStringTree, который скриптам не доступен. А от его родителей (TObject, TCompont, TControl и т.д.) толку мало, ну если только через Canvas(если он поддерживается) покрасить, но это все равно что через *опу. И как узнать в каком месте канвы рисовать?

Просмотр сообщенияНуПогоди (19.11.2007, 14:04) писал:

Только вот нужно будет разобраться во всех этих идиотских SW-панелях

Win32dasm'ом получилось выдрать даже описания свойств и методов для классов (типы, параметры), причем все так аккуратно, объявления класса, а сразу следом все его свойства и методы. Надо только немного почистить. Уже готовы "Ключевые слова, Функции\процедуры, Типы" - с моими небольшими коментариями (в SW не все работает из объявленного, например USES не пашет). Еще готовы "Базовые классы"(TObject, TComponent, ...) и "Невизуальные классы" (TStrings???, TStream???, и т.д.)

Из DFM'а выдрал, получилось этакое деревце :), только имя обекта и его тип (и отступами отношение к предыдущему), тоже прилеплю.
]

0

#30 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 20 Ноябрь 2007 - 12:23

Просмотр сообщенияD!ig (19.11.2007, 23:17) писал:

Плюс там что то еще хитрое с выравниванием команд.


Выравнивание команд однозначно работать не будет, так как неизвестно, каким образом движок интерпретирует команды и "кладёт" их в память.
0

#31 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 21 Ноябрь 2007 - 00:39

Цитата

А если есть другие идеи
  • YO_FILE = 'c:\Program Files\URUSOFT\Subtitle Workshop\PascalScripts\yo2_127.dat';

    -->
    YO_FILE = 'PascalScripts\yo2_127.dat';

    В скриптах можно использовать относительные пути

  • CONFIGFILE = 'c:\Windows\YO.ini';

    -->
    CONFIGFILE = 'YO.ini';

    А у меня Винда стоит не в 'c:\Windows' - это раз, Vista - туда может и не пустить, UAC верещать начнет (в этом не уверен, сам VIstu не ставил).

  • CRLF = ''#13''#10;

    -->
    CRLF = #13#10;

    объясните, ради бога, неучу, зачем кавычки? так не работает?

  • Grp1 := TGroupBox.Create(Application);

    Если владельцем сделать FORM, а не Application, тогда возможно (пусть Bedazzle разъянит) при уничтожении формы, все контролы, которыми она владеет, автоматически уничтожатся и Grp1.Free (и тд) будут не нужны.

  • {  Функция меняет все буквы «ёЕ» на букву «еЕ»  - Case Sensitive}
    function EFileName(st: String): String;
    коммент к функции не правильный

  • case varREGIME of
      FALSE: for k:=1 to m do // «Е»
      if src[k]='е' then 
      begin
    	result:=TRUE; exit;
      end;
      TRUE:	for k:=1 to m do // «Е» и «Ё»
      if (src[k]='е') or (src[k]='ё') then 
      begin
    	result:=TRUE; exit;
      end;
    end;

    -->
    for k:=1 to m do
    if (src[k]='е') or (varREGIME and (src[k]='ё'))
    then result:=TRUE; exit;

    вроде работает :wacko:

  • procedure Chk1Click(Sender: TObject);
    begin
    if Chk1.Checked and Chk2.Checked then Chk4.Visible:=TRUE else 	Chk4.Visible:=FALSE;

    -->
    Chk4.Visible := (Chk1.Checked and Chk2.Checked);

    так красивше :)

  • procedure Chk1Click(Sender: TObject);
    procedure Chk2Click(Sender: TObject);
    Chk1.onclick := @Chk1Click;
    Chk2.onclick := @Chk1Click;
    ...
    procedure Chk3Click(Sender: TObject);
    procedure Chk4Click(Sender: TObject);
    procedure Chk5Click(Sender: TObject);
    Chk3.onclick := @Chk3Click;
    Chk4.onclick := @Chk4Click;
    Chk5.onclick := @Chk5Click;

    -->
    procedure Chk12Click(Sender: TObject);
    Chk1.onclick := @Chk12Click;
    Chk2.onclick := @Chk12Click;
    ...
    procedure Chk345Click(Sender: TObject);
    Chk3.onclick := @Chk345Click;
    Chk4.onclick := @Chk345Click;
    Chk5.onclick := @Chk345Click;

    сократить количество обработчиков, они одинаковые

  • procedure SelectWord1(Sender: TObject);
    procedure SelectWord2(Sender: TObject);
    procedure Break(Sender: TObject);

    тоже можно объединить

  • ОКНО ДИАЛОГА ПРИ ОШИБКЕ
    ОКНО ДИАЛОГА ПРИ ОШИБКЕ ЧТЕНИЯ СЛОВАРЯ
    ОКНО ДИАЛОГА ДЛЯ СОМНИТЕЛЬНЫХ СЛОВ

    а не лучше при старте скрипта все окошки создать, а потом когда надо показывать?

  • try ts.LoadFromFile(CONFIGFILE);
    except
    // дефолтные параметры настроек скрипта

    -->
    result	:= FALSE;
    // дефолтные параметры настроек скрипта
    try ts.LoadFromFile(CONFIGFILE);
    finally
    strok:=ts.Count-1;
    for i:=0 to strok do
    ...
    result:=true;
    end;

    лучше дефолтные параметры назначить ДО загрузки конфига, к тому же файл может быть в наличии, но иметь длину 0 и тогда настройки у скрипта будут не правильные.

  • while(not IsSubtitleSelected(i)) do i:=i+1;	// ищем 1ый выбранный субтитр
    start:=i+1; 
    while(IsSubtitleSelected(i)) do i:=i+1;
    finish:=i;

    А ведь титры могут быть выбраны непоследовательно (2,5,10).
    И если 2й выбран 3й не выбран, 4-100 выбран, обработается только 2й

  • j:=Pos('#',YO[1]);	
    while j>0 do 					// убираeм из комментариев '# ' в начале строк
    begin
    Delete(YO[1],j,1);
    j:=Pos('#',YO[1]);
    end;

    -->
    for j := 1 to Length(YO[1])-1 do //перебираем символы в строке
    if (YO[1][J]=#13) or (YO[1][J]=#10)  // если это перевод каретки
      then bCR = true // устанавливаем флаг, что началась новая строка
      else if (YO[1][J]<>'#') // если символ не равен #
    		then begin
    		  s := s+YO[1][J]; // добавляем его в конец временной стрjки
    		  bCR := false;	 //снимаем флаг новой строки
    		end;
    YO[1] := s; // по завершении цикла присваиваем значение YO[1]

    выглядит массивно из-за комментариев, зато Pos'ов и Delete'ов нет.
    Если я нигде не ошибся, то вырежет все # строго в начале строк.

  • if not ((txt>='А') or (txt='ё') or (txt='Ё')) then	// всё, что попадает в разряд букв русского алфавита

    -->
    type TRuLetter = ('А','Б',...'я');//type TRuLetter = ('А'..'Я','а'..'я','Ё','ё'); 
    type TRuAlphabet = set of TRuLetter;
    var RuAlphabet : TAlphabet;
    ...
    if not (txt in RuAlphabet) then	// всё, что попадает в разряд букв русского алфавита

    Попробовать через set, хотя не уверен что получится. Не проверял. Так понятней.

  • MsgBox

    Applcation.MessageBox(text, caption, flags); // при flags=0 будет только кнопка ОК

    Ну, это просто информация.
-----
Кстати. Если интересно, могу сказать, где достать русскую справку по Delphi.
-----
» Offtopic «

0

#32 Пользователь офлайн   НуПогоди Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Избранные
  • Сообщений: 832
  • Регистрация: 31 Июль 06
  • Страна:
  • Прислал(a) субтитров: 46
  • Своих переводов: 19

Отправлено 21 Ноябрь 2007 - 12:38

D!ig, спасибо за титанический труд! Надеюсь, что к понедельнику поправлю...
0

#33 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 22 Ноябрь 2007 - 00:04

Просмотр сообщенияНуПогоди (21.11.2007, 11:38) писал:

D!ig, спасибо за титанический труд! Надеюсь, что к понедельнику поправлю...
:blush: Да ладно, чего там титанического, 10мин. на код поглядел.
0

#34 Пользователь офлайн   НуПогоди Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Избранные
  • Сообщений: 832
  • Регистрация: 31 Июль 06
  • Страна:
  • Прислал(a) субтитров: 46
  • Своих переводов: 19

Отправлено 27 Ноябрь 2007 - 16:16

Просмотр сообщенияD!ig (21.11.2007, 21:04) писал:

:blush: Да ладно, чего там титанического, 10мин. на код поглядел.

Просканировал твои замечания чуть детальнее... Кратко: пункты 3-5,7-9 и 11 я поправил. Там и говорить особо не о чем... Чуть подробнее о другом: о том, с чем не согласен (пп. 1, 2 & 6), что обломался делать из-за (не)здоровой лени (пп. 10, 13 & 14) и, наконец, о том, чего попросту не понял (п. 12).

Цитата

1-2. В скриптах можно использовать относительные пути
YO_FILE = 'PascalScripts\yo2_127.dat';
CONFIGFILE = 'YO.ini';

Можно... Вопрос лишь: откуда эти относительные пути будут отсчитываться или, по-русски, где находится текущая рабочая директория (cwd)? Если сначала запускать SW.ехе и открывать титры, пользуясь SW-меню, то cwd - действительно там, где лежит SW.exe и относительные пути типа 'PascalScripts\yo2_127.dat' будут приемлемы. Но, я, скажем, привык открывать сабы даблкликом из ТоталКомандера, многие делают то же самое из эксплорера. Что при этом получается, ты наверняка догадываешься: cwd = фолдер с открытыми титрами. В результате, при относительных путях в скрипте (вроде 'PascalScripts\yo2_127.dat') словарь будут искать в совсем другой папке и ессссно не найдут. Допустим, ты не поленишься и укажешь правильный путь к словарю в TEdit окошка DictionaryError. Но тебе придётся делать это снова и снова (для каждой папки, в которой хранятся сабы) и, как следствие, YO.ini будет "плодиться" во всех фолдерах, откуда открывались субтитры... Нет, нам такой хоккей не нужен!

Цитата

6. for k:=1 to m do
if (src[k]='е') or (varREGIME and (src[k]='ё'))
then result:=TRUE; exit;
вроде работает

Работает конечно, но медленнее: условие, которое нужно проверить только раз (varREGIME) в твоём варианте проверяется для каждой буквы слова (k=1..m).

Цитата

10. а не лучше при старте скрипта все окошки создать, а потом когда надо показывать?
За редким исключением окна открываются только один раз и только по мере надобности. Если окно не потребуется (а именно такой режим - "нормальный"), то зачем его сначала создавать, а потом, так и не использовав, устранять? В то самое редкое исключение входит окно с "сомнительными" словами да, с очень большой натяжкой, окошко с редактором пути к словарю (если тупой пользователь снова и снова вводит неправильный путь). Вот "сомнительное" окно я и поправил (ver 0.05): теперь оно создаётся только один раз (при необходимости) и один же раз убивается.

Цитата

12. А ведь титры могут быть выбраны непоследовательно (2,5,10).
Tы уверен? Я думал, что SW умеет выделять ТОЛЬКО последовательные сабы ХХX-YYY. Если тебе удалось выбрать, скажем, 2ой, 5ый и 10ый - расскажи, как ты это делаешь.

Цитата

13. выглядит массивно из-за комментариев, зато Pos'ов и Delete'ов нет.
Если я нигде не ошибся, то вырежет все # строго в начале строк.

Вырежет-то вырежет, только я не понимаю, чем тебе Pos & Delete не понравились. Я посмотрел: вся процедура подготовки скрипта к запуску, целиком (включая открытие Ё- и Е-файлов, их рассыпание на YO[1]..YO[33] и Е[1]..E[33] и вырезание десяти символов '#' из коротенького, всего 309 байт, кусочка текста) занимает на моём ЦПУ аж 121ms (а ему уже 5 лет, как минимум). Значит у других ещё быстрее будет. Так чего ради надрываться? Ну да чего только не сделаешь ради интереса! Взял твой вариант, выкинул лишнее и попробовал:
i:=i-1;
for j:=2 to i do				// остаётся скопировать только комменты в YO[1],
	if text[j]<>'#' then 		// убирая из комментариев # в начале строк
		YO[1]:=YO[1]+text[j];

Что получилось? 130-131ms. Потом попробовал суммировать не побуквенно, а текстовыми кусками (между старым и новым символами #). Вот так:
k:=2;						// начиная со второй буквы ищем # и, когда находим,
	for j:=2 to i-1 do			// суммируем прямо в YO[1] кусок до этого символа
		if text[j]='#' then 
			begin
			YO[1]:=YO[1]+Copy(text,k,j-k);
			k:=j+1;					// сдвигаем маркер для следущего копирования
			end;

Всё те же 130ms. Так что я остался при старом варианте (он имхо нагляднее и быстрее), а легенды о медленности Pos & Delete (для коротенького фрагмента, по крайней мере) сильно преувеличены.

Цитата

14. type TRuLetter = ('А','Б',...'я');
type TRuAlphabet = set of TRuLetter;
var RuAlphabet : TAlphabet;
...
if not (txt in RuAlphabet) then ...
Зачем? Не много ли чести для одного-единственного if? К тому же так, скорее всего, будет медленнее. Это условие стоит в основном цикле поиска, поэтому эксперименты тут оправданы только в том случае, если дают выигрыш в скорости. В новой версии я вообще это тройное условие разделил на две части: первое условие (ch<192) отрезает почти весь русский алфавит (т.е. до двух остальных условий - ch<>ё и ch<>Ё - дело доходит крайне редко). Так значительно быстрее получается.
0

#35 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 27 Ноябрь 2007 - 17:54

Просмотр сообщенияНуПогоди (27.11.2007, 14:16) писал:

Tы уверен? Я думал, что SW умеет выделять ТОЛЬКО последовательные сабы ХХX-YYY. Если тебе удалось выбрать, скажем, 2ой, 5ый и 10ый - расскажи, как ты это делаешь.


CTRL+клик мышой
0

#36 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 27 Ноябрь 2007 - 20:02

Просмотр сообщенияНуПогоди (27.11.2007, 15:16) писал:

Работает конечно, но медленнее: условие, которое нужно проверить только раз (varREGIME) в твоём варианте проверяется для каждой буквы слова (k=1..m).

Ok.

Просмотр сообщенияНуПогоди (27.11.2007, 15:16) писал:

За редким исключением окна открываются только один раз и только по мере надобности.
...
Вот "сомнительное" окно я и поправил (ver 0.05): теперь оно создаётся только один раз (при необходимости) и один же раз убивается.

Как скажешь начальник. :)

Просмотр сообщенияНуПогоди (27.11.2007, 15:16) писал:

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

Pos, точно также циклом, перебирает буквы в строке и сравнивает их с буквами в подстроке. При каждом вызове Pos он начинает перебор букв сначала. Идея была такова, заменив Pos на цикл можно избежать лишних проверок.

Delete - хрен его знает, как он работает.
Может Copy + SetLength, ну или просто 2хCopy если использовать временную переменную. А может циклом буквы сдвигает.

ИМХО.

Просмотр сообщенияНуПогоди (27.11.2007, 15:16) писал:

а легенды о медленности Pos & Delete (для коротенького фрагмента, по крайней мере) сильно преувеличены.

Надо еще учитывать, что мы имеем дело со скриптом. И накладные расходы на вызов Pos|Delete могут быть меньше чем от организации цикла. В Delphi надо будет потестировать.

Просмотр сообщенияНуПогоди (27.11.2007, 15:16) писал:

14. type TRuLetter = ('А','Б',...'я');
type TRuAlphabet = set of TRuLetter;
var RuAlphabet : TAlphabet;
...
if not (txt in RuAlphabet) then ...

Зачем? Не много ли чести для одного-единственного if? К тому же так, скорее всего, будет медленнее. Это условие стоит в основном цикле поиска, поэтому эксперименты тут оправданы только в том случае, если дают выигрыш в скорости. В новой версии я вообще это тройное условие разделил на две части: первое условие (ch<192) отрезает почти весь русский алфавит (т.е. до двух остальных условий - ch<>ё и ch<>Ё - дело доходит крайне редко). Так значительно быстрее получается.

Эксперимент я провел :). Снизу скрипт для тестирования. Работает ~20сек. потом выводит результат. Там 4 варианта проверок такого условия. Разница между самым быстрым и самым медленным 4-5раз!
» ... «


Просмотр сообщенияНуПогоди (27.11.2007, 15:16) писал:

Вопрос лишь: откуда эти относительные пути будут отсчитываться или, по-русски, где находится текущая рабочая директория (cwd)?

Проверил. Действительно если тыкнуть по srt файлу откроется SW, но Ёжификатор ругается на отсутсвие словаря.
Тогда можно использовать свойство ExeName объекта Application.
» ... «

Код набросал неглядя может где ошибся.

---
» offtopic «

0

#37 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 27 Ноябрь 2007 - 21:32

Просмотр сообщенияD!ig (27.11.2007, 18:02) писал:

» offtopic «


Имей терпение, добрый человек. Хотя бы до иксмаса. :)

Просмотр сообщенияD!ig (27.11.2007, 18:02) писал:

» offtopic2 «


Покажь!!!
0

#38 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 28 Ноябрь 2007 - 02:11

Цитата

А если есть другие идеи

Я в шоке. Последняя версия раздулась до 1300 строк. :cry2:
Собственно, для повышения производительности, больше, посоветовать ничего не могу. Могу немного побрюзжать, на остутствие компактного кода. :)
  • function IsYOEInside
    ...
    if varREGIME then
    	begin
    		...
    	result:=FALSE;		
    	end		
    else 
    	begin
    		...
    	result:=FALSE;	
    	end;	
    end;

    Result:=FALSE поставь первой строчкой функции, как дефолтное значение.
  • procedure Btn3Click(Sender: TObject);
    begin
    if DETAILS then
    	begin
    	Btn3.Caption:=' Спрятать детальное описание конфигурации ';
    	Btn1.Top:=Btn1.Top+DETAILS_HEIGHT;
    	Btn2.Top:=Btn2.Top+DETAILS_HEIGHT;
    	Form.Height:=Form.Height+DETAILS_HEIGHT;
    	Grp2.Visible:=not Grp2.Visible;
    	DETAILS:=not DETAILS;
    	end
    else
    	begin
    	Btn3.Caption:=' Показать детальное описание конфигурации ';
    	Btn1.Top:=Btn1.Top-DETAILS_HEIGHT;
    	Btn2.Top:=Btn2.Top-DETAILS_HEIGHT;
    	Form.Height:=Form.Height-DETAILS_HEIGHT;
    	Grp2.Visible:=not Grp2.Visible;
    	DETAILS:=not DETAILS;
    	end;
    end;

    -->
    procedure Btn3Click(Sender: TObject);
    var d: integer;
    begin
      if details then d := DETAILS_HEIGHT else d := DETAILS_HEIGHT * (-1);
    	Btn1.Top:=Btn1.Top+d;
    	Btn2.Top:=Btn2.Top+d;
    	Form.Height:=Form.Height+d;
    	Grp2.Visible:=not Grp2.Visible;
    	DETAILS:=not DETAILS;   
    end;

    Так букв меньше. :)
  • XXXXX.Left   	:= YY;
    XXXXX.Top		:= YY;
    XXXXX.Width	  := YYY;
    XXXXX.Height 	:= YYY;

    -->
    XXX.SetBounds(YY,YY,YYY,YYY);
    Такого там полно.
  • Form.Height	   := 338;
    if DETAILS then Form.Height  := Form.Height-DETAILS_HEIGHT;

    -->
    Form.Height  := 338 - (DETAILS_HEIGHT*byte(Details));
    ;)
  • //Btn1.Top		 := Form.Height+74;
    //if DETAILS then Btn1.Top:=Btn1.Top-DETAILS_HEIGHT;
    //	Btn1.Left		:= Grp1.Left;
    //	Btn1.Top  := Form.Height + 74 - (DETAILS_HEIGHT*byte(Details));  
    //	Btn1.Width	   := Grp1.Width/2-4;
    //	Btn1.Height	  := 25;

    -->
     Btn1.SetBounds(Grp1.Left, Form.Height + 74 - (DETAILS_HEIGHT*byte(Details)), Grp1.Width/2-4, 25);
    Некрасиво\непонятно?
    -->
     Btn1.SetBounds(Grp1.Left,															   // Left
    						 Form.Height + 74 - (DETAILS_HEIGHT*byte(Details)), // Top
    						 Grp1.Width/2-4,													  // Width
    						 25);																	   // Heigth
    :B
  • procedure CreateDoubtsWindow;

    Может убрать из нее установку размеров и позиций для создаваемых контролов? Вместо этого в конце вызвать DialogResize(form)? Ведь теже самые размеры, небось, устанавливает?
-----
» OFFTOPIC «
:bye:
0

#39 Пользователь офлайн   BedaZzle Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Admin
  • Сообщений: 2 987
  • Регистрация: 22 Октябрь 02
  • Страна:
  • Прислал(a) субтитров: 98
  • Своих переводов: 16

Отправлено 28 Ноябрь 2007 - 04:44

Просмотр сообщенияD!ig (28.11.2007, 0:11) писал:

А чего там показывать то. На данный момент, все что есть, это 2 MessageBox'a. 1-й вылазиет при загрузке DLL (читай старте SW), 2-й соответственно при выгрузке DLL (закрытии SW). В принципе очень легко воткнуть вызов DLL функции из любого обработчика используемого в SW.
Патча как такового тоже нет, я ручками поправил екзешник, но это мелочь. Если действительно интересно попробую сделать Patch.exe, выложить пропатченый SW.exe не могу (GPRS).


Я думал, ты всё-таки через скрипты длл заинжектил :)
Если просто на вызов какой-то функции подвесил загрузку своей длл - тогда пока повременим, может что более элегантное удастся изобрести.
0

#40 Пользователь офлайн   D!ig Иконка

  • Иконка
  • Отправить ЛС
  • Группа: Members
  • Сообщений: 140
  • Регистрация: 11 Март 06
  • Страна:

Отправлено 28 Ноябрь 2007 - 19:17

» OFFTOPIC «

0

  • (2 Страниц)
  • +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему