-
12.12.2008, 16:56 #1
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Вопрос по префиксам для лог. программ
Давно хотел задать вопрос по префиксам, назрел он давно, а сейчас в связи с написанием нового лога, стал очень актуальным.
Известно, что многие логи, написанные или пишущиеся сейчас используют в качестве базы файлы .cty, где содержистя вся информация о CQ Zone, ITU Zone. Вот именно об этом мой вопрос. Возьмем рассмотрим например, две ситуации:
1) CE9/KC4 (Antarctica) - СQ: 12, 13, 29, 30, 32, 38, 39 и ITU: 67, 69-74.
2) B (China) - СQ: 23, 24 и ITU: 33, 42, 43, 44.
Данные согласно DXCC List 2008. Для China существует деление по цифре в префиксе и первой букве суффикса, например: BY6Q - China (Hu Bei), СQ: 24, ITU: 44. И так далее. То есть можно составить некий "маппинг" для определения зон корректно. Однако для случая 1) ситуация более сложная. Так как например, префикс KC4 у нас используется для многих станций, например, McMurdo, Palmer, Byrd - все в разных зонах. Заносить в базу данных весь список, а он есть конечно, не совсем удобно, да и не рационально - он огромен просто. Сейчас мы в nGenLog используем именно такой "тупой" маппинг. И сие не есть оптимально.
Кроме этого есть и вторая, насущная проблема. Например для Аргентины: LU#G[A-O] - Chaco и LU#G[P-Z] - Formosa, при учете их на дипломы. Здесь нам необходимо отсечь сам префикс, например, LU1, затем определить первую букву суффикса - G, а далее проверить на оставшиеся буквы, чтобы точно определить провинцию. Сейчас делаем это на основе регулярных выражений (Regular Expression), но создать "универсальную" маску для сравнения пока не удается. Слишком много вариантов. Писать специальный парсер - может и идея, но тоже слишком много ветвлений.
Отсюда вопрос: существует ли наиболее удобный способ для решения данной проблемы? Кто как ее решал в своих логах, тем более многие из них на форуме обсуждались. Исходный код не нужен - нужна хорошая идея и алгоритм реализации.
Кто-нибудь может подсказать, как решить такую задачку? Любые идеи приветствуются.73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
-
13.12.2008, 01:19 #2
- Регистрация
- 04.09.2008
- Адрес
- Одесса, Украина
- Возраст
- 55
- Сообщений
- 1,959
- Записей в дневнике
- 2
- Поблагодарили
- 113
- Поблагодарил
- 161
В большинстве логов такая ситуация
Я Сам испытываю трудности
У меня тоже сложно определить, так как иногда станции передают зону отличную от стандарта.
Например в CQWW работает K5ZD и хотя WAZ зона 4 для K5 он передавал 5,
RT9S тоже не соответствовал - он передавал 16 зону
Я решил, да и в других логах необходимо заносить в базу префиксов этот позывной или префикс с указанием правильной зоны
С Аргентиной я решил так:
Код:Public Sub FindCountry(sCallsign As String) Dim rs As dao.Recordset Dim sMsg As String Dim Msg As String Dim msg1 As String Dim msg2 As String Dim IsLuBig As Boolean Dim length As Integer Dim SQLString As String Dim i As Integer Dim maxi As Integer Dim csign As String Dim aStr As String Dim Prefix As String On Error Resume Next If Len(sCallsign) = 0 Then Exit Sub If IsRuntime Then On Error GoTo ErrRtn Trace "Country FindCountry" ClearProperties csign = NormalizeCall(sCallsign) IsLuBig = False ' If IsValidCall(sCallsign) = False Then Exit Sub sMsg = csign length = Len(sCallsign) If length < 1 Then Exit Sub SQLString = "select * from prefix where Prefix = '" & sCallsign & "'" Set rs = LogDB.OpenRecordset(SQLString, dbOpenDynaset, dbReadOnly) If rs.BOF Or rs.RecordCount = 0 Then notFull = False Msg = Left$(csign, 2) msg1 = Mid$(csign, 4, 2) IsLuBig = (Len(msg1) > 0 And Msg = "LU") Select Case Msg Case "L1" To "L9" csign = Replace(csign, "L", "LU") msg2 = "LU" Case "LU", "LV", "LW" csign = Replace(csign, Msg, "LU") msg2 = "LU" Case "UR" To "UY", "EO", "EM", "EN" csign = Replace(csign, Msg, "UR") Case "U5" csign = "UR" & Mid$(csign, 2, 2) Case "UO", "UP", "UN" csign = Replace(csign, Msg, "UN") Case "RA" To "RZ", "UE" To "UI" csign = Replace(csign, Msg, "UA") Case "R0" To "R9", "U0", "U2" To "U4", "U6" To "U9" csign = "UA" & Mid$(csign, 2, 2) If sMsg = "R3K" Then csign = "UA3A" ' If Left(sMsg, 3) = "RA2" Or Left(sMsg, 3) = "UA2" Then csign = "RA2F" Case "FO", "FR" csign = Msg & "-" & LCase$(Right$(csign, 1)) ' Case "UA2" ' csign = "RA2F" '& LCase$(Right$(csign, 1)) Case Else Select Case Left$(csign, 4) Case "RO4M", "UA4M" csign = "UA4L" End Select End Select ' If IsLuBig Then ' это значит надо смотреть две буквы после префикса Select Case msg1 Case "XA" To "XO" csign = Replace(csign, msg1, "XA") Case "XP" To "XZ" csign = Replace(csign, msg1, "XP") Case "GA" To "GO" csign = Replace(csign, msg1, "GA") Case "GP" To "GZ" csign = Replace(csign, msg1, "GP") Case Else csign = "LU." & Mid$(csign, 4, 1) End Select End If With PrefixRS .Index = "Prefix" .Seek ">=", csign On Error Resume Next If .NoMatch Then .MoveLast If IsRuntime Then On Error GoTo ErrRtn If .BOF Then Exit Sub For i = 1 To .RecordCount Prefix = !Prefix 'If notFull Then ' Select Case ms1 ' ' ' ' Else If IsLuBig Then If InStr(Prefix, ".") > 0 Then If Mid$(csign, 4, 2) = Mid$(Prefix, 4, 2) Then Prefix = "LU." & msg1 Exit For End If ' .MovePrevious End If ' ElseIf Not IsLuBig Then ' If InStr(prefix, ".") > 0 Then ' If Mid$(csign, 4, 1) = Mid$(prefix, 4, 1) Then ' prefix = "LU." & Mid$(prefix, 4, 1) ' Exit For ' End If ' End If ElseIf InStr(Prefix, ".") > 0 And Mid$(Prefix, 4, 1) = Mid$(csign, 4, 1) Then If Len(Mid$(csign, 4, 1)) > 0 Then Prefix = Left$(Prefix, 2) & "." & Mid$(Prefix, 4, 1) Exit For End If ElseIf InStr(Prefix, "-") > 0 And LCase$(Mid$(Prefix, 4, 1)) = LCase$(Mid$(csign, 4, 1)) Then If Len(Mid$(csign, 4, 1)) > 0 Then ' csign = Replace(csign, Mid$(csign, 3, 1), "-") Prefix = Left$(Prefix, 2) & "-" & LCase$(Mid$(Prefix, 4, 1)) Exit For End If ' End If End If 'If Not station.CurrentContest.IsCQ And !IsStarred = 1 Then 'Else If Left$(csign, Len(Prefix)) = Prefix Then Exit For If Left$(csign, 1) <> Left$(Prefix, 1) And i > 1 Then Exit Sub If .BOF Then Exit Sub 'End If .MovePrevious If .BOF Then .MoveFirst Exit Sub End If Next 'i If Len(Prefix) = 0 Then Exit Sub End With If CountryPrefix = Prefix Then SetPrefixZones PrefixRS Trace "Country End FindCountry" Exit Sub End If SQLString = "select * from prefix where Prefix = '" & PrefixRS!Prefix & "'" Set rs = LogDB.OpenRecordset(SQLString, dbOpenDynaset, dbReadOnly) End If rs.MoveFirst FromRow rs, PrefixRS rs.close Set rs = Nothing Trace "Country End FindCountry" Exit Sub ErrRtn: ErrorHandler cmMDI, "FindCountry" End Sub
Вообщем так пока может кто-то решает по другомуLog4Win аппаратный журнал для повседневных связей и соревнований http://log4win.ucoz.net/
-
13.12.2008, 02:11 #3
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Игорь, спасибо за отклик... Кода я уже скопировал, он теперь переведен из VB в C# конвертером. Будем смотреть на производительность. В принципе мы где-то также делаем, но используем RegEx и как всегда имеем плюсы и минусы. Минусов пока больше... Я тут пытаюсь "колдовать" с сиквелом, используя в запросе IN и прочие ухищрения. Все только для повышения быстродействия. Одной идеей могу поделиться сразу, может пригодится. Мы используем для определения страны выделенные блоки префиксов (Prefix Allocation Block), например CL - CM для Кубы. В .NET есть метод String.CompareTo() или String.CompareOrdinal() позволяющий сравнить две строки. То есть первая то, что введено, а вторая эталонная из базы. При этом, данный метод работает быстрее, чем если тоже самое делать встроенными средствами сиквела, типа BETWEEN или другими. Что еще удобно, так то, что не надо использовать Switch...Case, так как вводимая строка идет, как параметр, а второй параметр - эталонная строка берется из запроса (Execute Scalar Query) к сиквелу. Где еще выигрышь в производительности? В сиквеле 2005 (да и в 2008) есть фича - CLR хост и Object Brocker. При этом исчезает напрочь потребность иметь дополнительный Data Access Layer. То есть у нас напрямую приложение работает с базой данных.
На что еще наткнулись - 8Q... да именно Мальдивы. Какой там континент? Во-во. Их два: AF/AS. Ну и какой нам использовать? Да, можно забить "по умолчанию" AS, а в контестах для кого-то множитель по континенту пролетит...
Однако проблема с антарктическими станциями все еще камень преткновения... и здесь я не знаю как быть. Да есть вся директория антарктических станций, но вбивать ее... мама мия... Есть мысли? Может сообща придумаем чего-то?73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
-
13.12.2008, 02:21 #4
- Регистрация
- 25.08.2006
- Адрес
- Шадринск, Курганская обл., Россия
- Возраст
- 37
- Сообщений
- 1,866
- Поблагодарили
- 175
- Поблагодарил
- 278
Госопода в качестве языка для парсера Рекомендую perl
у него очень мощная система регулярных выражений Так что много проблем решится скажем аргентина такой страшной казаться не будет.
Вот пример как я споты фильтрую:
if(($spot=~m/\s144\d\d\d\.\d\s/||$spot=~m/\s145\d\d\d\.\d\s/)
&&($spot=~m/<ES>/i||$spot=~m/\(ES>/i||$spot=~m/\sES\s/i))
{
print("ES_144!!!!\n");
open(ESSPOTFILE, ">> /var/log/sporadik/ES_144_file.spt") or die "can't open spot-file";
print ESSPOTFILE $spot;
close (ESSPOTFILE);
$spot="";
};
Регулярные выражения можно по компактнее вписать мне просто людей жалко кто будет с нуля пытаться их прочитать тогда.
А на счет языка C# это вы зря... смените пока не поздно...Для человека с молотком любая проблема кажется гвоздем.
Слава богу, теперь уже БЫВШИЙ член СРР, 73!
-
13.12.2008, 02:27 #5
- Регистрация
- 04.09.2008
- Адрес
- Одесса, Украина
- Возраст
- 55
- Сообщений
- 1,959
- Записей в дневнике
- 2
- Поблагодарили
- 113
- Поблагодарил
- 161
Последний раз редактировалось UR5FCM; 13.12.2008 в 02:30. Причина: Добавлено сообщение
Log4Win аппаратный журнал для повседневных связей и соревнований http://log4win.ucoz.net/
-
13.12.2008, 02:38 #6
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Для RA9QCE:
Насчет Perl, да великолепно... Нам любой язык годится... лишь бы задача решалась... А насчет C# - зачем же его менять? А главное на что? Где еще вы XAML, WPF, WCF найдете? Пока альтернатив нет. А Perl и под .NET тоже имеется, так что платформа очень универсальная - уже 57 языков поддерживает. Но я не о том, а о том, как задачку решить...
ПС Читать будет программер... от конечного пользователя все одно все скрыто будет...
Для UR5FCM:
"А если что-то типа UA-UI1,3,4,6,RA-RZ тут сложно пока" - Нее, не сложно. Я завтра кину простенький примерчик, как у нас это сделано с исходным кодом. Если есть VS 2005, то все прозрачно и понятно. Хранимые процедуры будут в базе - базу приложу в виде скрипта .sql или .ddl. Там все легко и тривиально. И можно улучшать.73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
-
13.12.2008, 02:40 #7
- Регистрация
- 25.08.2006
- Адрес
- Шадринск, Курганская обл., Россия
- Возраст
- 37
- Сообщений
- 1,866
- Поблагодарили
- 175
- Поблагодарил
- 278
С такими языками не знаю но вот скажем в проектах серьёзных, ну тот же matlab, все нормально с этим...
видимо проще всего отдельно вынести весь обработчик в perl... тут уже думать надо под unix с C и c++ связывается без проблем, возможно и в виндоус без .NET то же....Для человека с молотком любая проблема кажется гвоздем.
Слава богу, теперь уже БЫВШИЙ член СРР, 73!
-
13.12.2008, 02:41 #8
- Регистрация
- 04.09.2008
- Адрес
- Одесса, Украина
- Возраст
- 55
- Сообщений
- 1,959
- Записей в дневнике
- 2
- Поблагодарили
- 113
- Поблагодарил
- 161
Последний раз редактировалось UR5FCM; 13.12.2008 в 02:43. Причина: Добавлено сообщение
Log4Win аппаратный журнал для повседневных связей и соревнований http://log4win.ucoz.net/
-
13.12.2008, 02:44 #9
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Ну не будем же мы писать лог на MatLab...
Добавлено через 1 минуту
Ладно, юмор юмором, а вопрос я думаю не у меня одного такой... У нас там и немцы и швейцарцы в задумчивости "репу" чешут...Последний раз редактировалось RX1AL; 13.12.2008 в 02:45. Причина: Добавлено сообщение
73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
-
13.12.2008, 02:47 #10
- Регистрация
- 04.09.2008
- Адрес
- Одесса, Украина
- Возраст
- 55
- Сообщений
- 1,959
- Записей в дневнике
- 2
- Поблагодарили
- 113
- Поблагодарил
- 161
Log4Win аппаратный журнал для повседневных связей и соревнований http://log4win.ucoz.net/
-
13.12.2008, 02:49 #11
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Если VB.NET, Delphi под .NET и Perl под .NET - без проблем связываются. Поскольку все в CLR исполняется. А если через DLL, то придется писать wrapper и дергать методы и функции через P/Invoke. Других простых путей нет и не будет...
Добавлено через 4 минуты
Для UR5FCM:
На пример CallParser, написанный на дельфи - смотрел, и как раз самая первая идея была по улучшению. Однако и там те же грабли - вид сбоку. Алекс также загружает всю таблицу по антарктическим станциям - они там идут огроменным списком... Мы же хотим от всего этого по возможности отказаться... Иначе скоро придется сидюк выпускать для файла в формате .сty ... Не рационально.Последний раз редактировалось RX1AL; 13.12.2008 в 02:53. Причина: Добавлено сообщение
73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
-
13.12.2008, 02:56 #12
- Регистрация
- 25.08.2006
- Адрес
- Шадринск, Курганская обл., Россия
- Возраст
- 37
- Сообщений
- 1,866
- Поблагодарили
- 175
- Поблагодарил
- 278
вот наобум проверка вашей Аргентины, не проверял в компиляторе, пишу прямо в форуме,, но думаю должен работать
if(($call=~m/\AL[O-W]\dG[A-O]/){print"Chaco"};
if(($call=~m/\AL[O-W]\dG[P-Z]/){print"Formosa"};
Читабельно и просто...
А по поводу языков... Ну я сторонник C/C++ для проектов такого плана, нового ничего не придумали хорошего для этого, скрипты Perl, ну может ruby python для любителей... Процедурные языки - пока haskell более менее, пока не встречался с их необходимостью. А остальное ну зачем, тот же C# в чем его преимущество? просто индусам объяснить чуть быстрее и будут дешевые программеры в майкрософте трудится... У ну да еще TCL/TK LISP но это уже не по теме...
Добавлено через 1 минуту
если вы все же под .NET начали то уж и пишите если PERL там есть нормальный, по связке документацию по перл полистайте, я обычно банально через хэдеры связываю, perl все же на Си и под него и был затьочен..
Добавлено через 6 минут
По реализации я бы взял наиболее частый формат файла вашего cty сделал парсер чтобы из него сделать уже автоматически регулярные выражения и парсер для позывного будет уже автоматически обновляться при обновлении файла cty
Ладно я спать, 5 утра местного...Последний раз редактировалось RN9RQ; 13.12.2008 в 03:03. Причина: Добавлено сообщение
Для человека с молотком любая проблема кажется гвоздем.
Слава богу, теперь уже БЫВШИЙ член СРР, 73!
-
13.12.2008, 03:10 #13
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Сам Perl для меня не новый язык... Я на нем в свое время писал и много, когда еще cgi-bin был... Насчет С/С++ - спорить не собираюсь, так как сам сишник до мозга костей. Но сейчас уже не хочется возится с "DLL Hell" еще раз, когда есть полностью managed код. Да и под .NET никто С++ не отменял, он там тоже есть. Насчет С# - вы неправы во многом, ну да ладно... Он силен например, Generics (только не пытайтесь сравнивать с ATL ради бога - много общего, но и глубокая пропасть), возможностью работать с LINQ и напрямую с объектами из базы данных, а не с рекордсетом, что уже давно считается атавизмом...
По поводу регулярного выражения на перле - у вас там где-то ошибка, так как нет определения цифры в префиксе...
ПС Я не буду здесь насчет языков, а то топик улетит в ненужное русло... У каждого свой вкус и о них не спорят. Тем более я в том проекте лишь как сторонний программист, решение о выборе языка принимал не я и не мне его менять. Думаю так будет яснее...73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
-
13.12.2008, 03:25 #14
- Регистрация
- 25.08.2006
- Адрес
- Шадринск, Курганская обл., Россия
- Возраст
- 37
- Сообщений
- 1,866
- Поблагодарили
- 175
- Поблагодарил
- 278
цифра проверяется "\d" - одна любая цифра
расскажу сраху по порядку
"\A" - начало строки, чтобы он что-то в середине похожее не выхватил, можно решить модификатором оператора, отменив "жадность" но мне так больше нравится
L буква
L это понятно
[O-W] Диапазон букв по латинскому алфавиту от O до Z , поскольку аргентине выделен диапазон LOA-LWZ
далее одна любая цифра, кстати дааа цифр в спецпозывном может быть и много, значит надо после цифры поставить модификатор *
Все выражение будет \AL[O-W]\d*G[A-O]
Ну а далее по аналогии.
теперь \d* означает одна или несколько цифр
можно вписать и по другому \d{1,4} - все это значит от 1 до 4 цифр...Для человека с молотком любая проблема кажется гвоздем.
Слава богу, теперь уже БЫВШИЙ член СРР, 73!
-
13.12.2008, 03:31 #15
- Регистрация
- 12.03.2007
- Адрес
- Грац, Австрия - Санкт-Петербург, Россия
- Возраст
- 60
- Сообщений
- 1,749
- Поблагодарили
- 375
- Поблагодарил
- 160
Для RA9QCE:
Спасибо... Я именно это и имел в виду, когда и спец-позывной... А \d я просмотрел... каюсь... Тоже уже спать надо...
И Роман, раз вы у нас такой гуру в регулярных... ничего, если я вам завтра напишу с чем у нас затык, а вы напишете регулярные для этого? А уж как их встроить в класс RegEx на C# или на перл под дотнет - сие моя забота...73! Михаил (OE6MAF) :: HB9/OE6MAF, DL/OE6MAF
|
Социальные закладки