clone

an offline map explorer where each world, from a game map to a city's open data, ships as one .atlas file

main
atlas / internal / generate / sources / ign / capture.go
capture.go 2.9K
1package ign23import (4 "encoding/json"5 "sort"6)78// The archived capture, as the crawler wrote it: a wikimap's configuration, its9// marker types, and every marker. Its fields are structs and slices only,10// marshalled in declaration order, and normalize sorts its lists, so IGN11// returning the same markers in a different order does not masquerade as a new12// capture. Anything volatile on the page -- build ids, trace headers, timestamps13// -- was never captured; when a capture was taken is the archive's business.1415type capture struct {16 Source string `json:"source"`17 ObjectSlug string `json:"objectSlug"`18 MapSlug string `json:"mapSlug"`19 GameTitle string `json:"gameTitle"`20 MapTitle string `json:"mapTitle"`21 Map sheet `json:"map"`22 Types []kind `json:"types"`23 Markers []marker `json:"markers"`24}2526// sheet is the slice of IGN's page configuration a volume needs. Width and27// height are normalized to the map image: the taller dimension spans 1, so a28// marker's coordinates and the tile pyramid describe the same square world.29type sheet struct {30 Width float64 `json:"width"`31 Height float64 `json:"height"`32 MinZoom int `json:"minZoom"`33 MaxZoom int `json:"maxZoom"`34 InitialLat float64 `json:"initialLat"`35 InitialLng float64 `json:"initialLng"`36 BackgroundColor string `json:"backgroundColor"`37 Tileset string `json:"tileset"`38}3940// kind is one marker type. Types naming a parent gather under it in the legend;41// the rest share one heading.42type kind struct {43 TypeSlug string `json:"typeSlug"`44 TypeName string `json:"typeName"`45 ParentTypeSlug string `json:"parentTypeSlug,omitempty"`46 IconURL string `json:"iconUrl,omitempty"`47 IconWidth int `json:"iconWidth,omitempty"`48 IconHeight int `json:"iconHeight,omitempty"`49}5051// marker keeps every field IGN serves for a pin, including the ones a volume52// holds back. WikiPage names an article on IGN's own wiki, which an offline53// reader cannot follow, so it stays archived until something can be made of it.54// The raw messages pass through whatever shape IGN used, which their endpoint55// has not settled.56type marker struct {57 ID string `json:"id"`58 Lat float64 `json:"lat"`59 Lng float64 `json:"lng"`60 MarkerName string `json:"markerName"`61 MarkerSlug string `json:"markerSlug"`62 TypeSlug string `json:"typeSlug"`63 WikiPage string `json:"wikiPage,omitempty"`64 IconSlug json.RawMessage `json:"iconSlug,omitempty"`65 RegionID json.RawMessage `json:"regionId,omitempty"`66 ChecklistTaskID json.RawMessage `json:"checklistTaskId,omitempty"`67}6869func (c *capture) normalize() {70 sort.Slice(c.Types, func(a, b int) bool { return c.Types[a].TypeSlug < c.Types[b].TypeSlug })71 sort.Slice(c.Markers, func(a, b int) bool { return c.Markers[a].ID < c.Markers[b].ID })72}