Add randomized landing network story
Build and deploy Docker image / build (push) Successful in 1m59s
Build and deploy Docker image / build (push) Successful in 1m59s
This commit is contained in:
+1
-1
Submodule graphql-contracts updated: c5592754fc...ca08538d38
+112
@@ -112,6 +112,26 @@ export const typeDefs = `#graphql
|
||||
distanceKm: Float
|
||||
}
|
||||
|
||||
enum LandingNetworkKind {
|
||||
HUB
|
||||
SUPPLIER
|
||||
}
|
||||
|
||||
type LandingNetworkPoint {
|
||||
uuid: String!
|
||||
kind: LandingNetworkKind!
|
||||
name: String!
|
||||
country: String
|
||||
latitude: Float!
|
||||
longitude: Float!
|
||||
distanceKm: Float
|
||||
}
|
||||
|
||||
type LandingNetworkStory {
|
||||
focus: LandingNetworkPoint!
|
||||
neighbors: [LandingNetworkPoint!]!
|
||||
}
|
||||
|
||||
type OfferNode {
|
||||
uuid: String
|
||||
productUuid: String
|
||||
@@ -177,6 +197,7 @@ export const typeDefs = `#graphql
|
||||
nearestHubs(lat: Float!, lon: Float!, radius: Float, productUuid: String, limit: Int): [Node!]!
|
||||
nearestOffers(lat: Float!, lon: Float!, radius: Float, productUuid: String, hubUuid: String, limit: Int): [OfferWithRoute!]!
|
||||
nearestSuppliers(lat: Float!, lon: Float!, radius: Float, productUuid: String, limit: Int): [Supplier!]!
|
||||
landingNetworkStory(focusKind: LandingNetworkKind!, neighborLimit: Int): LandingNetworkStory!
|
||||
routeToCoordinate(offerUuid: String!, lat: Float!, lon: Float!): ProductRouteOption
|
||||
hubsList(limit: Int, offset: Int, country: String, transportType: String, west: Float, south: Float, east: Float, north: Float): [Node!]!
|
||||
suppliersList(limit: Int, offset: Int, country: String, west: Float, south: Float, east: Float, north: Float): [Supplier!]!
|
||||
@@ -237,6 +258,93 @@ function mapOffer(doc: ArangoDoc, catalog = new Map<string, ProductCatalogItem>(
|
||||
}
|
||||
}
|
||||
|
||||
type LandingNetworkKind = 'HUB' | 'SUPPLIER'
|
||||
|
||||
function mapLandingNetworkPoint(doc: ArangoDoc, kind: LandingNetworkKind) {
|
||||
return {
|
||||
uuid: doc._key,
|
||||
kind,
|
||||
name: doc.name,
|
||||
country: doc.country ?? null,
|
||||
latitude: doc.latitude,
|
||||
longitude: doc.longitude,
|
||||
distanceKm: doc.distance_km ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveLandingNetworkStory(focusKind: LandingNetworkKind, neighborLimit?: number) {
|
||||
const db = getDb()
|
||||
const limit = Math.max(1, Math.min(neighborLimit ?? 3, 6))
|
||||
const focusCursor = await db.query(focusKind === 'HUB' ? `
|
||||
FOR hub IN nodes
|
||||
FILTER hub.node_type == 'logistics' OR hub.node_type == null
|
||||
FILTER hub.product_uuid == null
|
||||
FILTER hub.latitude != null AND hub.longitude != null
|
||||
SORT RAND()
|
||||
LIMIT 1
|
||||
RETURN hub
|
||||
` : `
|
||||
FOR supplier IN nodes
|
||||
FILTER supplier.node_type == 'supplier'
|
||||
FILTER supplier.latitude != null AND supplier.longitude != null
|
||||
SORT RAND()
|
||||
LIMIT 1
|
||||
RETURN supplier
|
||||
`)
|
||||
const focus = await focusCursor.next() as ArangoDoc | undefined
|
||||
if (!focus) throw new Error(`No ${focusKind.toLowerCase()} is available for the landing network story`)
|
||||
|
||||
if (focusKind === 'SUPPLIER') {
|
||||
const neighborsCursor = await db.query(`
|
||||
FOR hub IN nodes
|
||||
FILTER hub.node_type == 'logistics' OR hub.node_type == null
|
||||
FILTER hub.product_uuid == null
|
||||
FILTER hub.latitude != null AND hub.longitude != null
|
||||
LET dist = DISTANCE(hub.latitude, hub.longitude, @lat, @lon) / 1000
|
||||
SORT dist ASC
|
||||
LIMIT @limit
|
||||
RETURN MERGE(hub, {distance_km: dist})
|
||||
`, { lat: focus.latitude, lon: focus.longitude, limit })
|
||||
const neighbors = await neighborsCursor.all()
|
||||
return {
|
||||
focus: mapLandingNetworkPoint(focus, 'SUPPLIER'),
|
||||
neighbors: neighbors.map((neighbor: ArangoDoc) => mapLandingNetworkPoint(neighbor, 'HUB')),
|
||||
}
|
||||
}
|
||||
|
||||
const neighborsCursor = await db.query(`
|
||||
FOR offer IN nodes
|
||||
FILTER offer.node_type == 'offer'
|
||||
FILTER offer.supplier_uuid != null
|
||||
FILTER offer.latitude != null AND offer.longitude != null
|
||||
LET dist = DISTANCE(offer.latitude, offer.longitude, @lat, @lon) / 1000
|
||||
COLLECT supplier_uuid = offer.supplier_uuid INTO offers
|
||||
LET first_offer = FIRST(offers).offer
|
||||
LET supplier_dist = DISTANCE(first_offer.latitude, first_offer.longitude, @lat, @lon) / 1000
|
||||
LET supplier_node = FIRST(
|
||||
FOR supplier IN nodes
|
||||
FILTER supplier._key == supplier_uuid
|
||||
FILTER supplier.node_type == 'supplier'
|
||||
RETURN supplier
|
||||
)
|
||||
SORT supplier_dist ASC
|
||||
LIMIT @limit
|
||||
RETURN {
|
||||
_key: supplier_uuid,
|
||||
name: supplier_node != null ? supplier_node.name : first_offer.supplier_name,
|
||||
country: supplier_node != null ? supplier_node.country : first_offer.country,
|
||||
latitude: supplier_node != null ? supplier_node.latitude : first_offer.latitude,
|
||||
longitude: supplier_node != null ? supplier_node.longitude : first_offer.longitude,
|
||||
distance_km: supplier_dist
|
||||
}
|
||||
`, { lat: focus.latitude, lon: focus.longitude, limit })
|
||||
const neighbors = await neighborsCursor.all()
|
||||
return {
|
||||
focus: mapLandingNetworkPoint(focus, 'HUB'),
|
||||
neighbors: neighbors.map((neighbor: ArangoDoc) => mapLandingNetworkPoint(neighbor, 'SUPPLIER')),
|
||||
}
|
||||
}
|
||||
|
||||
async function loadProductCatalog() {
|
||||
const res = await fetch(EXCHANGE_GRAPHQL_URL, {
|
||||
method: 'POST',
|
||||
@@ -460,6 +568,10 @@ export const resolvers = {
|
||||
},
|
||||
|
||||
Query: {
|
||||
landingNetworkStory: async (_: unknown, args: { focusKind: LandingNetworkKind; neighborLimit?: number }) => {
|
||||
return resolveLandingNetworkStory(args.focusKind, args.neighborLimit)
|
||||
},
|
||||
|
||||
node: async (_: unknown, args: { uuid: string }) => {
|
||||
const db = getDb()
|
||||
const nodesCol = db.collection('nodes')
|
||||
|
||||
Reference in New Issue
Block a user