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
|
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 {
|
type OfferNode {
|
||||||
uuid: String
|
uuid: String
|
||||||
productUuid: String
|
productUuid: String
|
||||||
@@ -177,6 +197,7 @@ export const typeDefs = `#graphql
|
|||||||
nearestHubs(lat: Float!, lon: Float!, radius: Float, productUuid: String, limit: Int): [Node!]!
|
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!]!
|
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!]!
|
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
|
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!]!
|
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!]!
|
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() {
|
async function loadProductCatalog() {
|
||||||
const res = await fetch(EXCHANGE_GRAPHQL_URL, {
|
const res = await fetch(EXCHANGE_GRAPHQL_URL, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -460,6 +568,10 @@ export const resolvers = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Query: {
|
Query: {
|
||||||
|
landingNetworkStory: async (_: unknown, args: { focusKind: LandingNetworkKind; neighborLimit?: number }) => {
|
||||||
|
return resolveLandingNetworkStory(args.focusKind, args.neighborLimit)
|
||||||
|
},
|
||||||
|
|
||||||
node: async (_: unknown, args: { uuid: string }) => {
|
node: async (_: unknown, args: { uuid: string }) => {
|
||||||
const db = getDb()
|
const db = getDb()
|
||||||
const nodesCol = db.collection('nodes')
|
const nodesCol = db.collection('nodes')
|
||||||
|
|||||||
Reference in New Issue
Block a user