RU:Catalog/Zverik

From OpenStreetMap Wiki
Jump to navigation Jump to search

Это переработка схемы ErshKUS. Скопирую сюда список основных целей:

  1. Полный перевод тегов, для понимания обычного человека
  2. Конвертация в пресеты JOSM
  3. Создания иерархии элементов для различных каталогов/списков и её однородность
  4. Организации списка "правильных" тегов, для пользователей и валидаторов

Сделаем несколько дополнительных утверждений:

  • Одна запись описывает один объект, определяемый одним или несколькими тегами. При этом если какой-то тег используется в паре и отдельно, это должны быть различные объекты, иначе второй тег -- дополнительный.
  • Дополнительные теги модифицируют свойства объекта, не изменяя его принципиально. Например, fee=*. Эти теги не группируются, их значения могут быть произвольны.
  • Дополнительные теги могут объединяться в общие группы. Например, name, opening_hours, operator, brand, phone, fax, website -- общая группа "poi".
  • Основные теги фиксированы, значения дополнительных тегов могут варьироваться.
  • Все теги и дополнительные теги имеют идентификаторы, на которые ссылается перевод, и могут ссылаться внешние базы данных.

Большей частью схема основана на формате пресетов Potlatch 2 (см. раздел ссылок). Автор этого редактора неоднократно указывал на применимость формата для создания общего каталога тегов.

Каталог создаётся в формате JSON, как наиболее актуальном для современных приложений. Он состоит из единственного файла схемы и нескольких файлов перевода. Также см. /Форматы и /SQL.

Схема

Каталог -- это массив из объектов, тип которых определяется по ключу type. Каждый объект должен иметь идентификатор в ключе name, уникальный в пределах файла. Он может состоять только из латинских букв, цифр и знака подчёркивания, и должен начинаться с буквы.

Любые объекты или группы объектов могут быть объединены в группу. При этом связь может быть не древовидной, но сетевой, "многие ко многим". Так, shop=car_parts может одновременно входить в группу магазинов и POI для автомобилистов. Однако большинство инструментов требует древовидную структуру групп, поэтому первая группа из списка "родителей" считается главной, остальные могут быть отброшены.

Метаинформация

Первым элементом всегда идёт запись метаинформации. Все описанные ключи обязательны. Этот документ описывает версию формата 0.2 (описание не окончательное, формат может значительно меняться). Также см. #История изменений.

Ключ Значения Описание
type meta Обозначает запись метаинформации.
name Catalog Строка с названием формата.
version число с плавающей точкой Номер версии вида N.M (например, 1.2). Мажорная версия увеличивается при несовместимости нового формата со старым (например, когда type для дополнительного тега стал массивом, а не строкой), минорная -- когда изменения незначительны и не ломают совместимость (например, новый ключ в словаре).
timestamp время в формате ISO 8601 Время создания файла каталога.

Версии

У каждого объекта верхнего уровня (т.е. объекта с ключом type, не вложенного структурно в другие) присутствует хэш version со следующими обязательными полями:

Ключ Значения Описание
id целое положительное число Номер версии, начинается с 1 и увеличивается при каждом изменении данных.
author строка Имя пользователя в OpenStreetMap, изменившего данные.
uid целое положительное число Идентификатор пользователя в OSM. Может быть равен нулю: это означает автоматический импорт.
timestamp время в формате ISO 8601 Время последнего изменения записи.

Группа объектов

Группы служат двум целям. Во-первых, это теги для объектов и классов дополнительных тегов со связью "многие ко многим". Так, объект может входить в группы магазинов и автомобильных магазинов, которые вложены одна в другую. Во-вторых, из них можно построить древовидную структуру, какая встречается в пресетах и каталогах POI. Поэтому желательно, чтобы между группами не было связей A->B->A, хотя циклы из четырёх и более групп допустимы.

Ключ Значения Обязателен? Описание
type group да Обозначает группу объектов.
name идентификатор да Идентификатор группы.
group массив идентификаторов групп нет Если это подгруппа, нужно указать одну или несколько родительских групп.

Объект

Если какой-то объект по тегам подпадает под несколько описаний, берётся самое точное: так, если есть объекты для highway=service и highway=service + service=parking_aisle, то когда указаны оба тега, должен использоваться последний.

Ключ Значения Обязателен? Описание
type feature да Обозначает объект.
name идентификатор да Идентификатор объекта.
group массив идентификаторов групп нет Можно указать одну или несколько родительских групп.
applies массив из node/way/area/relation/changeset да Указывает типы объектов, к которым применимо это определение.
tags хэш { "тег" : "значение", ... } да Теги, определяющие этот объект (обычно одна или две пары). Если у объекта нет общего значения, то указать вместо него пустую строку (см. поле values). Второй тег становится основным, если его нельзя считать поясняющим основной. Т.е. сущность, выраженная основным тегом, качественно отличается от основного+дополнительного тега.
values массив значений нет Если объект определяется одним и только одним тегом, можно задать список значений, которые он может принимать. Например, для building=yes могут быть альтернативы building=apartments, building=garage и т.д.
deprecated true/false нет Если true, способ обозначения объекта устарел и не рекомендуется к использованию. Современные способы нужно указать в sameas и в словаре.
attributes массив дополнительных тегов нет Дополнительные теги для этого объекта. Теги из этого списка имеют приоритет перед определёнными в классах.
members массив членов отношения нет Для отношений -- описание членов.
classes массив идентификаторов классов нет Классы дополнительных тегов для этого объекта. Если теги в классах пересекаются, приоритет имеет класс, указанный в списке первым.
related массив идентификаторов нет Идентификаторы связанных с этим определением объектов, групп и классов.
sameas массив идентификаторов и ссылок на доп. теги нет Чаще всего -- ссылки на дополнительные теги (вида name.key, где name -- идентификатор содержащего доп. тег объекта или класса), наличие которых обозначает присутствие описываемого здесь объекта. Пример: amenity=atm и atm=yes. Также ссылки на объекты, эквивалентные этому: shop=insurance и office=insurance.

Член отношения

В схеме могут указываться теги для отношений. Состав члены отношений тоже можно регламентировать, через массив members. Элементы этого массива имеют следующий формат:

Ключ Значения Обязателен? Описание
role строка да Роль объекта в отношении.
name идентификатор нет Идентификатор записи для словаря. Ему достаточно быть уникальным в пределах массива членов отношения. По умолчанию равен полю role, для пустой роли -- "empty".
applies массив из node/way/area/relation да Типы объектов, которые могут содержаться в этой роли.
features массив идентификаторов нет Если в этой роли могут быть только определённые объекты (например, больницы) или группы (например, дороги), они перечисляются в списке.
required true/false нет Если true, требуется хотя бы один член в этой роли.
count число нет Ограничение на количество членов в этой роли.

Дополнительный тег

Дополнительные теги могут указываться только как элементы массива attributes объекта или класса. Поэтому поле type у них означает нечто совсем иное. В словарях на дополнительные теги ссылаются с упоминанием родительского элемента, поэтому можно, хотя и не рекомендуется, делать одинаковые идентификаторы в разных объектах или классах.

Ключ Значения Обязателен? Описание
key ключ тега да Ключ тега.
synonym другой ключ нет У некоторых ключей есть синоним: например, phone и contact:phone. В качестве синонима нужно указывать менее популярный вариант.
name идентификатор нет Идентификатор поля. По умолчанию равен key с вырезанными символами, не подходящими для идентификатора.
important true/false нет Если true, дополнительный тег очень желателен для простановки. Например, ref на highway=trunk.
suffixes массив суффиксов нет Список допустимых суффиксов для ключа.
type массив из free/text/
boolean/variant/number/speed/period
да Допустимые типы значений тега (см. ниже).
range [ min, max, step ] нет Для типа number можно указать границы значений: например, [-5,5,1] для ключа level.
values массив значений нет Для типа variant здесь перечисляются возможные значения.
default значение нет Значение, когда тег не задан. Для типа boolean это "yes" или "no".

Возможные типы:

Тип Описание
text Строка в свободной форме.
boolean Значение да/нет. Может принимать разнообразные значения: yes/no/true/false/1/0 и т.п.
variant Один из заданного списка вариантов. Считается, что пустая строка -- тоже всегда вариант (но ей не нужно присутствовать в списке).
number Число.
speed Скорость: число плюс суффикс единиц измерения: "40" или "30 mph".
period Значение opening_hours=*.

У тега может быть не только несколько значений (тип variant), но несколько типов значений: например, для lit=* типы будут ["boolean", "period", "variant"].

Класс дополнительных тегов

Ключ Значения Обязателен? Описание
type class да Обозначает объект.
name идентификатор да Идентификатор класса.
group массив идентификаторов групп нет Можно указать одну или несколько групп, к которым относится класс.
attributes массив дополнительных тегов да Дополнительные теги, характерные для этого класса объектов.
suffixes массив суффиксов нет Список допустимых суффиксов для всех тегов этого класса.
classes массив идентификаторов классов нет Классы могут содержать другие классы. Так, класс "poi" может включать классы "address" и "contact".

Суффикс

Ключи дополнительных тегов иногда уточняются суффиксами: name:en=*, maxspeed:forward=*. Суффиксы делятся на категории: направление, язык, валюта и т.п. Для особых значений суффикса могут быть категории только из одного элемента. Также см. /Суффиксы.

Ключ Значения Обязателен? Описание
type suffix да Обозначает категорию суффиксов.
name идентификатор да Идентификатор категории суффиксов.
values массив строк да Список суффиксов этой категории.

Пример

[
  {
    "type": "meta",
    "name": "Catalog",
    "version": "0.1",
    "timestamp": "2012-11-05T08:58:00Z"
  },
  {
    "type": "group",
    "name": "trade"
  },
  {
    "type": "feature",
    "name": "shop_supermarket",
    "group": ["trade"],
    "tags": {"shop": "supermarket"},
    "attributes": [
      {
        "key": "toilets",
        "type": ["boolean"]
      }
    ],
    "class": ["poi"],
    "applies": ["node", "area"]
  },
  {
    "type": "group",
    "name": "services"
  },
  {
    "type": "feature",
    "name": "amenity_bank",
    "group": ["services"],
    "tags": {"amenity": "bank"},
    "attributes": [
      {
        "key": "atm",
        "type": ["boolean"]
      },
      {
        "key": "atm2",
        "type": ["boolean"]
      }
    ],
    "class": ["poi"],
    "applies": ["node", "area"]
  },
  {
    "type": "feature",
    "name": "amenity_toilets",
    "group": ["services"],
    "tags": {"amenity": "toilets"},
    "class": ["poi"],
    "applies": ["node", "area"]
  },
  {
    "type": "class",
    "name": "poi",
    "attributes": [
      {
        "key": "name",
        "type": ["text"],
        "suffixes": ["language"],
        "important": "true"
      },
      {
        "key": "operator",
        "type": ["text"]
      },
      {
        "key": "opening_hours",
        "type": ["period"]
      }
    ]
  },
  {
    "type": "suffix",
    "name": "language",
    "values": ["en", "ru", "de", "fr", "uk", "be", "fi", "se", "es", "it"]
  },
  {
    "type": "feature",
    "name": "restriction",
    "applies": ["relation"],
    "tags": {"type": "restriction"},
    "attributes": [
      {
        "key": "restriction",
        "type": ["variant"],
        "values": ["no_right_turn", "no_left_turn", "no_u_turn", "no_straight_on",
            "only_right_turn", "only_left_turn", "only_straight_on"],
        "important": "true"
      },
      {
        "key": "except",
        "type": ["variant"],
        "values": ["psv", "bicycle", "hgv", "motorcar"]
      }
    ],
    "members": [
      {
        "role": "from",
        "applies": ["way"],
        "required": "true",
        "count": 1
      },
      {
        "role": "to",
        "applies": ["way"],
        "required": "true",
        "count": 1
      },
      {
        "role": "via",
        "applies": ["node", "way"],
        "required": "true"
      },
      {
        "role": " location_hint",
        "applies": ["node"],
        "count": 1
      }
    ]
  },
  {
    "type": "class",
    "name": "lit",
    "attributes": [
      {
        "key": "lit",
        "type": ["variant", "boolean", "period"],
        "values": ["automatic"]
      }
    ]
  }
]

Словарь

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

Общая структура

Все ключи объединяются в группы по типам, все ключи обязательны (но могут быть пустыми):

Ключ Значение Описание
language [ "код языка IETF", "название" ] Код языка, указывает, для какого языка это перевод, вместе с названием языка (на самом языке).
features хэш записей Строки для объектов и групп.
attributes хэш записей Строки для дополнительных тегов.
members хэш записей Строки для членов отношений.
suffixes хэш записей Строки для категорий суффиксов.
values хэш переводов Переводы общих значений, вроде yes и no.

Идентификаторы

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

  • для features и suffixes -- поле name;
  • для attributes -- составной ключ "name.key", где name -- идентификатор содержащего атрибут feature или class. Если в описании атрибута присутствует поле name, то используется "name.attribute_name". Можно использовать для атрибута ключ в виде просто key, тогда он будет использован при отсутствии более специфичного перевода. Работает наследование: сначала проверяется название объекта, затем -- название класса. Например, можно перевести "bank.operator" независимо от перевода атрибута класса "poi.operator" и общего перевода "operator".
  • для members -- тоже составной ключ "name.role" ("name.empty" для пустой роли) или "name.member_name", когда указано поле name. В отличие от атрибутов, общие переводы указывать нельзя, роли всегда зависимы от отношений.

Запись

Единственным обязательным ключом в записи является name, но очень желательно указать максимальное количество ключей.

Ключ Значение Описание
name строка Название объекта или группы на человеческом языке.
description строка Расширенное описание объекта или группы.
values хэш хэшей записей При наличии поля values у объекта; для дополнительного атрибута типа variant; для суффиксов указывается хэш вида { "значение1": {name: "перевод1", ...}, "значение2": {name: "перевод2", ...} }. Структура переводов такая же, как для записей. В случае объектов нужно указывать только поля, замещающие основные. Для суффиксов ключами в этом хэше хэшей являются названия суффиксов.
link url Ссылка на описание объекта или группы в интернете.
wiki название статьи Название статьи в вики OpenStreetMap, например, "RU:Link (highway)". Для преобразования в ссылку все пробелы заменяются на знаки подчёркивания, в начало добавляется "http://wiki.openstreetmap.org/wiki/".
image url картинки Ссылка на фотографию или иное изображение объекта.
keywords массив строк Набор ключевых слов, по которым можно найти этот объект или группу.
boolean [ "перевод для yes", "перевод для no" ] Только для дополнительного тега типа boolean: Две строки: перевод для положительного и отрицательного значения. Должно содержать тип. например, для fee: [ "Бесплатно", "Платно" ]. Если не указано, используется обычный формат "Название: перевод значения".
absent строка Только для дополнительного тега: Строка, используемая при отсутствии тега на объекте. Например, для name -- "Без названия". При наличии флага important это поле обязательно.
version хэш версии Информация о последнем изменении записи, смотрите описание хэша в разделе "Схема".

Перевод

Раздел переводов обычных значений имеет однообразную структуру, так как таких значений немного. Для простоты сразу напишем её в JSON:

"values": {
  "absent": "не указано",
  "boolean": {
    "yes": "есть",
    "no": "нет"
  },
  "speed": {
    "mph": "м/ч",
    "kph": "км/ч",
    "default": "км/ч"
  },
  "period": {
    "Mo": "пн",
    ...
    "Su": "вс",
    "Jan": "янв",
    ...
    "Dec": "дек",
    "24/7": "круглосуточно",
    "off": "закрыто"
  },
  "version" {
    ...
  }
}

Значение absent используется только для дополнительных тегов с флагом important. Описание хэша "version" смотрите в разделе "Схема".

Пример

{
  "language": ["ru", "Русский"],
  "features": {
    "trade": {"name": "Торговля"},
    "services": {"name": "Услуги"},
    "shop_supermarket": {"name": "Супермаркет", "description": "Торговая точка больше обычного магазина",
        "wiki": "RU:Tag:shop=supermarket", "keywords": ["магазин", "супермаркет"]},
    "amenity_bank": {"name": "Банк", "description": "Отделение банка", "wiki": "RU:Tag:amenity=bank", "keywords": ["банк", "деньги"]},
    "amenity_toilets": {"name": "Туалет"},
    "restriction": {"name": "Запрет поворота", "description": "Отношение устанавливает ограничения направлений движения на перекрёстках",
        "wiki": "RU:Relation:restriction", "keywords": ["поворот", "перекрёсток", "запрет", "знак", "ограничение"]}
  },
  "attributes": {
    "atm": {"name": "Банкомат", "description": "Присутствует ли рядом или внутри банкомат"},
    "amenity_bank.atm2": {"name": "Дополнительный банкомат"},
    "toilets": {"name": "Туалет", "description": "Наличие туалета", "boolean": ["Есть туалет", "Туалета нет"]},
    "poi.name": {"name": "Название", "absent": "Без названия"},
    "poi.operator": {"name": "Владелец"},
    "poi.opening_hours": {"name": "Время работы"},
    "restriction.restriction": {"name": "Разрешённые направления движения", "values": {
        "no_right_turn": {"name": "прямо и налево"}, "no_left_turn": {"name": "прямо и направо"}, "no_u_turn": {"name": "запрещён разворот"},
        "no_straight_on": {"name": "налево и направо"}, "only_right_turn": {"name": "только направо"},
        "only_left_turn": {"name": "только налево"}, "only_straight_on": {"name": "только прямо"}
    }}
  },
  "members": {
    "restriction.from": {"name": "Откуда", "description": "Отрезок дороги, откуда едет транспортное средство"},
    "restriction.to": {"name": "Куда"},
    "restriction.via": {"name": "Через", "description": "Точка перекрёстка или набор промежуточных линий"},
    "restriction.location_hint": {"name": "Знак", "description": "Место для рисования значка запрета на карте"}
  },
  "suffixes": {
    "language": {"name": "Язык", "description": "Перевод значения тега на другие языки", "values": {
      "en": {"name": "английский", "description": "Значение на английском языке"},
      "de": {"name": "немецкий"}, "ru": {"name": "русский"}, "fr": {"name": "французский"}
    }}
  },
  "values": {
    "absent": "неизвестно",
    "boolean": {
      "yes": "есть",
      "no": "нет"      
    }
  }
}

История изменений

Версия Что изменилось
0.1 Первая версия.
0.2
  • Хэш версий для структур схемы, записей и переводов словаря. Теперь JSON будет эквивалентен SQL.
  • Объекты типа entrance=yes/main/service/... определяются полем values.
  • Ключ sameas отделён от related в объектах.
  • Идентификаторы должны начинаться с латинских букв.

Источники