image

Прилетела мне недавно задача дополнить функционал одной довольно старой програмки (исходного кода программы нет). По сути нужно было просто сканить периодически БД, анализировать информацию и на основе этого совершать рассылки. Вся сложность оказалась в том, что приложение работает с БД c-tree, написанной аж в 1984 году.

Порывшись на сайте производителя данной БД нашёл некий odbc драйвер, однако у меня никак не получалось его подключить. Многочисленные гугления так же не помогли нормально сконнектиться с базой и доставать данные. Позже было решено связаться с техподдержкой и попросить помощи у разработчиков данной базы, однако ребята честно признались что уже прошло 34 года, всё поменялось 100500 раз, нормальных драйверов для подключения на такое старьё у них нет и небось уже тех программистов в живых тоже нету, которые писали сие чудо.
Порывшись в файлах БД и изучив структуру, я понял, что каждая таблица в БД сохраняется в два файла с расширением *.dat и *.idx. Файл idx хранит информацию по id, индексам и т.д. для более быстрого поиска информации в базе. Файл dat содержит саму информацию, которая хранится в табличках.

Решено было парсить эти файлики самостоятельно и как-то добывать эту информацию. В качестве языка использовался Go, т.к. весь остальной проект написан на нём.

Я опишу только самый интересные моменты, с которыми я столкнулся при обработке данных, которые в основном затрагивают не сам язык Go, а именно алгоритмы вычислений и магию математики.

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

image

Вдохновляющую фразочку я получил от клиента с небольшим описанием, почему так:”**** was a MS-DOS application running on 8086 processors and memory was scarce”.

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

  • начало и конец файла (размер всегда разный) зарезервированы под табличные данные
  • длина строки в таблице занимает всегда одно и то же количество байт
  • вычисления проводятся в 256ричной системе

Время в расписании


В приложении создаётся расписание с интервалом в 15 минут (Например 12:15 – 14:45). Потыкав в разное время, нашёл область памяти, которая отвечает за часы. Я считываю данные из файла побайтово. Для времени используется 2 байта данных.

Каждый байт может содержать значение от 0 до 255. При добавлении в расписание 15 минут в первый байт добавляется число 15. Плюсуем ещё 15 минут и в байте уже число 30 и т.д.
Например у нас следующие значения:

[0] [245]

Как только значение превышает 255, в следующий байт добавляется 1, а в текущий записывается остаток.

245 + 15 = 260
260 – 256 = 4


Итого имеем значение в файле:

[1] [4]

А теперь внимание! Очень интересная логика. Если это диапазон с 0 минут до 45 минут в часе, то в байты добавляется по 15 минут. НО! Если это последние 15 минут в часе (с 45 до 60), то в байты добавляется число 55.

Получается что 1 час всегда равен числу 100. Если у нас 15 часов 45 минут, то в файле мы увидим такие данные:

[6] [9]

А теперь включаем немного магии и переводим значения из байтов в целое число:

6 * 256 + 9 = 1545

Если разделить это число на 100, то целая часть будет равна часам, а дробная – минутам:

1545/100 = 15.45

Кодяра:

data, err := ioutil.ReadFile(defaultPath + scheduleFileName)
	if err != nil {
		log.Printf("[Error] File %s not found: %v", defaultPath+scheduleFileName, err)
	}

	timeOffset1 := 98
	timeOffset2 := 99
	timeSize := 1

	//first 1613 bytes reserved for table
	//one record use 1598 bytes
	//last 1600 bytes reserved for end of table
	for position := 1613; position < (len(data) - 1600); position += 1598 {
		...
		timeInBytesPart1 := data[(position + timeOffset2):(position + timeOffset2 + timeSize)]
		timeInBytesPart2 := data[(position + timeOffset1):(position + timeOffset1 + timeSize)]
		totalBytes := (int(timeInBytesPart1[0]) * 256) + int(timeInBytesPart2[0])
		hours := totalBytes / 100
		minutes := totalBytes - hours*100
		...
	}

Дата в расписании


Логика работы вычисления значения из байт для дат такая же как и во времени. Байт заполняется до 255, затем обнуляется, а в следующий байт добавляется 1 и т.д. Только для даты уже было выделено не два, а четыре байта памяти. Видимо разработчики решили, что их приложение может прожить ещё несколько миллионов лет. Получается, что максимальное число, которое мы можем получить равно:

[255] [255] [255] [256]
256 * 256 * 256 * 256 + 256 * 256 * 256 + 256 * 256 + 256 = 4311810304


Эталонная стартовая дата в приложении равна 31 декабря 1849. Конкретную дату считаю путём добавления дней. Я изначально знаю, что AddDate из пакета time имеет ограничение и не сможет скушать 4311810304 дней, однако на ближайшие лет 200 хватит).
Проанализировав приличное количество файлов я нашёл три варианта расположения дат в памяти:
  • считывание байт, конкретного участка памяти, необходимо проводить слева направо
  • считывание байт, конкретного участка памяти, необходимо проводить справа налево
  • между каждым «полезным байтом» данных вставляется нулевой байт. Например [1] [0] [101] [0][100] [0] [28]

Мне так и не удалось понять, зачем использовалась разная логика для расположения данных, но принцип подсчёта даты везде одинаковый, главное правильно доставать данные.

Кодяра:

func getDate(data []uint8) time.Time {
	startDate := time.Date(1849, 12, 31, 0, 00, 00, 0, time.UTC)
	var result int

	for i := 0; i < len(data)-1; i++ {
		var sqr = 1
		for j := 0; j < i; j++ {
			sqr = sqr * 256
		}

		result = result + (int(data[i]) * sqr)
	}

	return startDate.AddDate(0, 0, result)
}

Расписание доступности


У сотрудников есть расписание доступности. В день можно назначить до трёх интервалов времени. Например:

8:00 – 13:00
14:00 – 16:30
17:00 – 19:00


Расписание может быть назначено на любой день недели. Мне необходимо было сгенерировать расписание на ближайшие 3 месяца.

Вот примерная схема хранения данных в файле:

image

Я вырезаю из файла каждую запись по отдельности, затем смещаюсь на определённое количество байт в зависимости от дня недели и там уже обрабатываю время.

Кодяра:

type Schedule struct {
	ProviderID string                  `json:"provider_id"`
	Date       time.Time               `json:"date"`
	DayStart   string                  `json:"day_start"`
	DayEnd     string                  `json:"day_end"`
	Breaks     *ScheduleBreaks         `json:"breaks"`
}

type SheduleBreaks []*cheduleBreak

type ScheduleBreak struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

func ScanSchedule(config Config) (schedules []Schedule, err error) {
	dataFromFile, err := ioutil.ReadFile(config.DBPath + providersFileName)
	if err != nil {
		return schedules, err
	}

	scheduleOffset := 774
	weeklyDayOffset := map[string]int{
		"Sunday":    0,
		"Monday":    12,
		"Tuesday":   24,
		"Wednesday": 36,
		"Thursday":  48,
		"Friday":    60,
		"Saturday":  72,
	}

	//first 1158 bytes reserved for table
	//one record with contact information use 1147 bytes
	//last 4494 bytes reserved for end of table
	for position := 1158; position < (len(dataFromFile) - 4494); position += 1147 {
		id := getIDFromSliceByte(dataFromFile[position:(position + idSize)])
		//if table border (id equal "255|255"), then finish parse file
		if id == "255|255" {
			break
		}
		position := position + scheduleOffset
		date := time.Now()
		//create schedule on 3 future month (90 days)
		for dayNumber := 1; dayNumber < 90; dayNumber++ {
			schedule := Schedule{}
			offset := weeklyDayOffset[date.Weekday().String()]
			from1, to1 := getScheduleTimeFromBytes((dataFromFile[(position + offset):(position + offset + 4)]), date)
			from2, to2 := getScheduleTimeFromBytes((dataFromFile[(position + offset + 1):(position + offset + 4 + 1)]), date)
			from3, to3 := getScheduleTimeFromBytes((dataFromFile[(position + offset + 2):(position + offset + 4 + 2)]), date)

			//no schedule on this day
			if from1.IsZero() {
				continue
			}

			schedule.Date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, time.UTC)
			schedule.DayStart = from1.Format(time.RFC3339)

			switch {
			case to3.IsZero() == false:
				schedule.DayEnd = to3.Format(time.RFC3339)
			case to2.IsZero() == false:
				schedule.DayEnd = to2.Format(time.RFC3339)
			case to1.IsZero() == false:
				schedule.DayEnd = to1.Format(time.RFC3339)
			}

			if from2.IsZero() == false {
				scheduleBreaks := ScheduleBreaks{}
				scheduleBreak := ScheduleBreak{}
				scheduleBreak.Start = to1
				scheduleBreak.End = from2
				scheduleBreaks = append(scheduleBreaks, &scheduleBreak)
				if from3.IsZero() == false {
					scheduleBreak.Start = to2
					scheduleBreak.End = from3
					scheduleBreaks = append(scheduleBreaks, &scheduleBreak)
				}
				schedule.Breaks = &scheduleBreaks
			}
			date = date.AddDate(0, 0, 1)
			schedules = append(schedules, &schedule)
		}
	}
	return schedules, err
}

//getScheduleTimeFromBytes calculate bytes in time range
func getScheduleTimeFromBytes(data []uint8, date time.Time) (from, to time.Time) {
	totalTimeFrom := int(data[0])
	totalTimeTo := int(data[3])

	//no schedule
	if totalTimeFrom == 0 && totalTimeTo == 0 {
		return from, to
	}

	hoursFrom := totalTimeFrom / 4
	hoursTo := totalTimeTo / 4
	minutesFrom := (totalTimeFrom*25 - hoursFrom*100) * 6 / 10
	minutesTo := (totalTimeTo*25 - hoursTo*100) * 6 / 10
	from = time.Date(date.Year(), date.Month(), date.Day(), hoursFrom, minutesFrom, 0, 0, time.UTC)
	to = time.Date(date.Year(), date.Month(), date.Day(), hoursTo, minutesTo, 0, 0, time.UTC)

	return from, to
}

В целом хотелось просто поделиться знаниями о том, какими алгоритмами вычислений пользовались раньше.

Комментарии (51)


  1. Akuma
    20.03.2018 19:55

    приложение работает с БД c-tree и написано аж в 1984 году

    В качестве языка использовался Go, т.к. весь остальной проект написан на нём.

    Это как?


    1. pda0
      20.03.2018 20:01
      +1

      В качестве языка для современной программы, которая вычитала данные и которая ими потом пользовалась. (Т.е. старую DOS программу на go переписали.)

      А вообще, «безумству храбрых поём мы песню». Т.е. вариант установить в виртуалку или DOSBox тот самый DOS, подцепиться к базе софтом того времени, склепать простенькую программу, которая сбросит все таблицы в csv даже не рассматривался. Ясно.


      1. mxis Автор
        20.03.2018 22:21

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


        1. khim
          21.03.2018 03:00

          Если вам для всего этого не приходится заводить эмулятор какого-нибудь Mac'а, на котором эмулируется PDP-11 (или, хуже того, PDP-10) то это так себе «древность». Вот компьютерное железо бывшее новинкой сразу после 2й мировой — это да.


          1. mxis Автор
            21.03.2018 10:02

            К счастью до такого не дошло)))


  1. 4eyes
    20.03.2018 20:36
    +2

    вычисления проводятся в 256ричной системе
    Очень режет глаз. Если не секрет, есть пара вопросов.

    * программирование — это основная часть вашей профессиональной деятельности?
    * если да, то есть ли базовые (академические) знания в C/C++, языке ассемблера, архитектуре ПК?

    То, что вы так подробно описали про дату и время, сокращается до трёх предложений:
    Время — 2-байтный int в формате HHMM
    Дата — 4-байтный int, означающий число дней с (...).
    Оба целых записываются в файл в порядке little-endian.


    1. khim
      20.03.2018 21:20

      Да тут «не режет глаз»! Тут в качестве «открытий» преподносятся вещи, на которых и сегодня, по большому счёту, все операционки и весь интернет построен.

      Статья на уровне: «мне тут потребовалось как-то починить автомобиль середины прошлого века, а ни один сервис его в починку не брал… я капот открыл — а там такая крутилка… и палка изогнутая, к ней поршни прикручены».

      Кому это нужно? И зачем? Нет, я понимаю — для индувидуального развития оно, может, и неплохо. Но как-то уж очень много в последнее время на Хабре изобретателей велосипедов…


      1. mxis Автор
        20.03.2018 21:59

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


        1. khim
          20.03.2018 23:05

          Ну и зачем им вся эта «вода»? Описание формата, похожее на описание DBF было бы гораздо полезнее.

          Как бы любой уважающий себя программист должен умерть вынуть структуру из файла, если её формат описан. То есть вот те три строки которые написал 4eyes — были бы весьма полезны, да. Но зачем же картинки рисовать, где показано как из отдельных байтов складывается струкура int16_t [7][3][2];? Это, как бы, должно быть достаточно очевидно читающему и так…


          1. fukkit
            21.03.2018 14:10
            +2

            вынуть структуру из файла, если её формат описан

            Это ж рутина, тлен и — к индусам.
            А вот в отсутствии знания получить и систематизировать опыт — весьма полезное умение. Имхо, автор — молодец. Надоест велосипедить — книжк почитать никогда не поздно.


            1. khim
              21.03.2018 19:21

              вынуть структуру из файла, если её формат описан
              Это ж рутина, тлен и — к индусам.
              Тем не менее изобретению кривого велосипеда, это осуществляющего, посвящана почти вся статья. Специфики собственно c-tree — с гулькин нос, зато «вычисления в 256-ричной системе счисления» — на виду.

              А ничего, что никакие «вычисления в 256-ричной систем» тут не нужны, а нужен разбор бинарных данных, для которого даже в стандарнтной библиотеке Go есть специальные компоненты, нет?

              А вот в отсутствии знания получить и систематизировать опыт — весьма полезное умение.
              Несомненно. До достаточно ли этого для того, чтобы писать статьи? Вы себе представляете статью на форуме краснодеревщиков от автора не знающего о том, что такое токарный станок и чем он отличается от фрезировального или на форуме любителей кройки и шитья от человека не знаючего чем потайной шов отличается от прямого смёточного шва?

              Надоест велосипедить — книжк почитать никогда не поздно.
              А после этого — и статью написать можно, да.

              Задумайтесь вот над чем: я на Go не пишу, но, тем не менее, за 5 минут нашёл в стандартной библиотеке компонент посвящённый решению той задачи, которую тут навелосипедил автор статьи. Потому что я знаю какую задачу тут решают, знаю что для её решения должен быть компонент — и оп-па, он там таки есть.

              Автор этого не сделал, несмотря на то, что у него, вроде как «весь остальной проект написан на нём». О чём это говорит?

              Ну честное слово, домашняя работа пятикласника и аналитическая работа в политический журнал — разные жанры, они оцениваются по разному! Тут, правда, знаний чуть побольше, чем у пятикласника, да и Хабр — не вполне на уровне рецензируемых журналов, но… идея понятна, нет?


              1. olegchir
                21.03.2018 19:45

                mxis не обращай внимание на фанатиков из этого треда, ты молодец! Продолжай дальше!


        1. j_wayne
          21.03.2018 17:07

          ИМХО для этого куда эффективнее задать вопрос на StackOverflow и ответить самому на него.


    1. mxis Автор
      20.03.2018 22:01

      На оба вопроса ответ — да.
      Писака из меня не очень, согласен, но за критику спасибо, я учту


    1. ZurgInq
      21.03.2018 10:29
      +4

      У меня есть подозрение, что таких «базовых знаний» нет у подовляющего большинства веб программистов. И при этом формально, «программирование» — основная сфера профессиональной деятельности.


  1. Yeah
    20.03.2018 22:25

    Это она? http://www.faircom.com/v11-5-is-here


    Пишут, что последняя версия выпущена в 2017-м. И есть какой-то web interface


    1. mxis Автор
      20.03.2018 22:28

      Всё верно. И интерфейс есть, и документации куча, и драйвера подключения… Только всё это к новым версиям, а не к такой старой, которой владею я.


      1. 4eyes
        21.03.2018 14:41

        Писака нормальный, просто была интересна причина столь подробного изложения.

        Было впечатление, что автор студент и только что открыл для себя порядок байт и представление целых чисел в памяти. В таком случае, вам есть что почитать, чтобы следующая подобная задача далась проще.

        Или, что это не «оригинальное исследование», но вам хотелось разжевать представление целых для начинающих. В таком случае, любопытно, что вы не ограничились ссылками на википедию.

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


        1. 4eyes
          21.03.2018 14:55

        1. olegchir
          21.03.2018 19:48

          > Было впечатление, что автор студент и только что открыл для себя порядок байт и представление целых чисел в памяти.

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

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


          1. 4eyes
            21.03.2018 20:29

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

            Прямо скажем, это почти никому не нужно, кроме узкой касты системщиков.
            • и геймдевщиков
            • и сетевиков
            • и десктопщиков
            • и кодировщиков (видео, изображения)
            • и бекендщиков (тех, кто получает данные по сети от мобильного приложения и от десктопа одновременно)
            • и джаваскриптщиков*


            * джаваскриптщикам это не нужно ровно до тех пор, пока они не начнут использовать какой-нибудь API, в котором timestamp — это int. С некоторых пор они обнаружат, что (time_stamp + 1 == time_stamp ), хотя (time_stamp * 2 != time_stamp ). Пример такого API — twitter.


            1. khim
              21.03.2018 23:25

              На самом деле не нужно никаких API.

              Простйший пример на JavaScript:

              a = 9007199254740992;
              if (a + 1 === a) {
                // Пошли странные вещи
              }
              


              Проблема в том, что вся шаткая пирамида надстроенная над этими байтами и битами — состоит из протекающих абстракций.

              Так что обходиться без знания основ вы можете только до тех пор, пока результат разработки «тап-ляп и в продакшн» является нормой.

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

              Есть ощущение, что после этого старые отмазки что «вы заплатили за софт три копейки и, в случае чего, эти три копейки назад и получите» (что только и позволяет подходу «тап-ляп и в продакшн» существовать) — перестанут действовать. Как они не действуют во многих других областях (если от вашей банки с соком умрёт семья из трёх человек, то и производитель и продавец получат проблем куда на большую сумму, чем стоимость этой банки).

              Возможно тогда подход «мне „всю эту фигню“ знать не нужно — мои ж поделки не всегда падают, а только через два раза на третий» станет несколько менее популярным.

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


  1. olartamonov
    20.03.2018 22:46
    +2

    Каждый байт может содержать значение от 0 до 255


    В статье содержится большое количество полезной информации.


    1. ratijas
      20.03.2018 22:56
      +1

      Ну come on, годная техническая статья новичка в области байтослерарства. Прокачается — будет что-то поинтереснее реверсить. Не стоит перебирать с сарказмом, так ведь и обломать можно.


      1. olartamonov
        21.03.2018 10:26
        +2

        От программиста обычно ожидается некоторая ясность мысли и умение обращаться с int16 без магии.


      1. midday
        21.03.2018 17:16
        +1

        Ой коммон. Этот чел даже уроки в школе прогуливал по переводу систем счисления. Он как-то в 4 байта умудрился запихать 4311810304. Как? Когда там 4294967296 комбинаций. 256^4. А из систем счисления переводят так:
        255 * 256^3 + 255*256^2 + 255*256^1 + 255*256^0 = 4294967295
        А за комменты снизу о деградации, карму слили мне. А пацану подняли. Вот она самодеградация хабра.


        1. 4eyes
          21.03.2018 21:12

          Думаю, это не деградация, а разделение труда.

          Знаете, бывает глубокий экзистенциальный кризис, когда закрыл последний тег и задумался: в школе меня мучили алгеброй, в институте — вышкой, дискреткой, архитектурой ПК, а еще алгоритмами и структурами данных. И заставляли писать hello world в синем монстре Borland С-крест-крест. Оказалось, всё — тлен (кроме пчёл). Можно было идти работать после 9 класса и не тратить время в пустую.

          Так вот сейчас, похоже, действительно можно работать после 9 класса. Без систем счисления и всего этого. И разрабатывать сайты при должном уровне опыта быстрее и качественнее тру-сишника. Говорю вам как один из любителей приплюснутого си, который написал для домашнего использования фронт-энд к консольной утилите на express js — я слабо пригоден к такой работе.

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


          1. khim
            21.03.2018 23:37
            +1

            Так вот сейчас, похоже, действительно можно работать после 9 класса. Без систем счисления и всего этого. И разрабатывать сайты при должном уровне опыта быстрее и качественнее тру-сишника.
            Тут скорее вопрос: а зачем вообще разрабатывать «по кругу» одни и те же сайты, умеющие, по большому счёту, то, что сайты умели ещё лет 20, от силы, 10 лет назад.

            Вот что такого полезного научился за последние 10 лет делать Хабр, что оправдало бы несколько происшедших редизайнов?

            У меня есть ощущение, что мы наблюдаем очередной дотком, когда люди выкидывают деньги на создание вещей, которые, в общем, никому особо и не нужны — что порождает повышенный спрос на программистов, такой, что даже те, кто решили «пойти работать после 9 класса забив на все основы» находят себе применение.


          1. 0xd34df00d
            21.03.2018 23:47

            Так вот сейчас, похоже, действительно можно работать после 9 класса.

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

            Была у меня возможность пойти работать, правда, после 11-го класса, правда, после физмат-школы и, правда, с этак 4-5 годами плюсов за спиной на тот момент, но я таки зачем-то пошёл в вуз. И вот пошёл, значит, и познакомился с математикой, с теорией групп там всякой, с прочей абстрактной алгеброй и понял, что я дно и тупой, писать тупой же код на плюсах при этом с течением времени стало уныло, и всё стало тленом. Потом я ещё стал углублять знакомство, познакомился с теорией типов, со всякими там идрисами, и писать на плюсах опердни стало совсем уныло, а от питона вообще скулы сводит и лучше увольте.

            А мог бы сразу после 11-го класса зарабатывать под сотню килорублей, что для 2008 года было неплохо, и не париться с этим всем.


            1. Apatic
              22.03.2018 11:56

              зарабатывать под сотню килорублей, что для 2008 года было неплохо

              Неплохо? Учитывая среднюю зп по России в 2008 году (17,5к) да, для одиннадцатиклассника «неплохо» :)


              1. 0xd34df00d
                22.03.2018 18:33

                География несколько дисконтирует эти цифры (я тогда в Дефолт-Сити жил), но да, это несколько осложняло правильный выбор.


                1. Apatic
                  22.03.2018 18:58

                  Да даже для Москвы) До сих пор средняя по Мск ниже, чем 100к. Понятно, что в IT зп выше, но все равно.


          1. olartamonov
            22.03.2018 21:52

            Так вот сейчас, похоже, действительно можно работать после 9 класса


            Так и раньше можно было. Слесарь там, токарь второго разряда. Ну максимум в ПТУ немного подучиться.

            Или вы считаете, что в 2018 году «делать вебсайты» — это что-то сильно более перспективное, чем точить болванки в 1988-м?


    1. 0xd34df00d
      21.03.2018 23:42
      +1

      Ну, вообще говоря, не все байты восьмибитные.


      1. MacIn
        22.03.2018 00:22
        +1

        Сразу вспоминается старомодное «объем памяти — 2К восьмиразрядных слов» и т.п.


    1. 0xd34df00d
      21.03.2018 23:49

      del


  1. PastorGL
    20.03.2018 23:25

    BTW, для разбора бинарных форматов существуют специализированные инструменты.


  1. midday
    21.03.2018 10:51
    -6

    Вот они современные программисты.
    Грусть печаль. Вы в университете хоть учились?


  1. Apatic
    21.03.2018 12:56
    +24

    Ну прекратите. Что это за упражнения «кто больше унизит автора и скажет, что он недопрограммист»? К чему эта желчь? Комплексы что ли?

    Я ставлю плюс статье просто хотя бы потому, что даже если это и вода и основы, то это техническая вода и технические основы. А не очередное пространное эссе-сочинение на тему «почему я не люблю HR» / «как нам обустроить Россию IT» / «как я ненавижу 1С» / унылая статья ни о чем из корпоблога / etc, которыми нынче заполонен Хабр.

    Человек столкнулся с технической проблемой и рассказал, как решил ее, выложил код и алгоритмы. Плохо решил ли, хорошо ли — все это можно сказать и обсудить корректно. Вместо этого ответ — потоки желчи и упражнения в «остроумии». Причем зачастую от людей, не разместивших ни одной статьи.


    1. Whuthering
      21.03.2018 13:57
      +1

      Я понимаю и в целом поддерживаю ваше мнение, изложенное в комментарии (плюсик поставил), но также хочу отметить…

      Причем зачастую от людей, не разместивших ни одной статьи.

      … что "сперва добейся" и Ad Hominem в приличном обществе как-то не считаются нормальными доводами, которые стоит озвучивать.


    1. midday
      21.03.2018 16:12
      -2

      Согласен. Пора привыкать, что хабр — место для школьников.


      1. MikailBag
        21.03.2018 23:41

        Есть у меня подозрение, что full-аккаунты преимущественно у взрослых.


    1. Maccimo
      21.03.2018 20:55

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


  1. MacIn
    21.03.2018 20:18

    Очень интересная логика. Если это диапазон с 0 минут до 45 минут в часе, то в байты добавляется по 15 минут. НО! Если это последние 15 минут в часе (с 45 до 60), то в байты добавляется число 65.

    Получается что 1 час всегда равен числу 100

    Как ни силился, не смог понять, что имеется в виду. Гранулярность учета времени — 15 минут?
    Первые 45 минут добавляется по 15 минут, т.е. по итогу будет то же — 45. Потом 65, что даст сумму 110, но тут сумма — всегда 100, как указано.


    1. 4eyes
      21.03.2018 20:30

      формат времени — HHMM, где HH — 2 цифры часов, MM — 2 цифры минут. 1145 = «11:45». 1145+20 = 1205.


      1. MacIn
        21.03.2018 20:51

        Ах, вот оно что… «Получается что 1 час всегда равен числу 100» мда…
        Спасибо за перевод.


        1. khim
          22.03.2018 00:01

          Могли бы в код посмотреть.

          Там же ясно написано:

          hours := totalBytes / 100
          minutes := totalBytes - hours*100
          
          Откуда с одной стороны, становится ясно, что имел в виду автор, а с другой — как раз и порождает тот поток комментариев, что мы тут наблюдаем.

          Почему, чёрт побери, не
          hours := totalBytes / 100
          minutes := totalBytes % 100
          

          Это попытка «запутать противника»? До индусского кода — рукой подать. Я понимаю, если бы речь шла о каком-то экзотическом языке программирования, где остатка от деления нету… но в Go-то он есть! И в JavaScript есть. И в Basic есть… тогда зачем? И почему?

          И так — почти вся статья…


          1. MacIn
            22.03.2018 00:23

            Спасибо, но мне не очень интересно reverse-engineer'ить мысли автора и формат по коду. Я проглядел статью, чтобы получить представлеие о формате БД. Некоторе время назад приходилось разбираться с БД на основе b-tree из 90х, но там формат был сложнее — еще был файл блокировок.

            Интересно, компилятор оптимизирует последовательные операции деления и получения остатка с учетом того, что div выдает сразу оба?


            1. MacIn
              22.03.2018 00:29

              Да и то, что есть в этих кусках, есть и в статье:

              Если разделить это число на 100, то целая часть будет равна часам, а дробная – минутам:
              1545/100 = 15.45

              Лично мне это не объяснило ни «Получается что 1 час всегда равен числу 100», ни про 65, ни комбинацию этих двух в одном абзаце.


              1. khim
                22.03.2018 01:42

                Лично мне это не объяснило ни «Получается что 1 час всегда равен числу 100», ни про 65, ни комбинацию этих двух в одном абзаце.
                «Мясник так видит»… чего вы хотите от человека, открывшего для себя «256-ричную систему счисления»? Хотя как описать тот формат, что в этом чуде изобрели строго формально — я даже не знаю… и главное, непонятно: зачем.

                Потому что делить на 100 — как бы не сильно проще, чем делить на 60… есть подозрение что там у них общая процедура для времени и числ с десятичной фиксированной точкой… но так как этим всем автор статьи не игрался, то всё это осталось «за кадром»…


            1. khim
              22.03.2018 01:36

              Я проглядел статью, чтобы получить представлеие о формате БД.
              А в статье и нет этой информации. Индексы (то есть, собственно, c-tree) проигнорированы, из строчек таблицы выцеплено крошечное подмножество… так-то, для того, для чего этот модуль делали — этого, наверное, и достаточно… но к более-менее полноценному описанию формата эта статья не подбирается даже и близко.