v0.0.4
This commit is contained in:
70
cloudfunctions/nearbyPets/index.js
Normal file
70
cloudfunctions/nearbyPets/index.js
Normal file
@@ -0,0 +1,70 @@
|
||||
const cloud = require('wx-server-sdk')
|
||||
|
||||
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||
const db = cloud.database()
|
||||
|
||||
function hashId(id) {
|
||||
let h = 5381
|
||||
for (let i = 0; i < id.length; i++) {
|
||||
h = ((h << 5) + h) ^ id.charCodeAt(i)
|
||||
h = h >>> 0 // keep as unsigned 32-bit
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// Generate a stable map pin position from pet id (fallback abstract layer)
|
||||
function stablePin(id) {
|
||||
const h = hashId(id)
|
||||
const left = 10 + (h % 70)
|
||||
const top = 15 + ((h >> 8) % 55)
|
||||
return { left, top }
|
||||
}
|
||||
|
||||
// Scatter a pet deterministically within roughly ±0.9km of the user, so on a
|
||||
// real map markers cluster nearby (stable per pet id across requests).
|
||||
function syntheticCoord(id, userLoc) {
|
||||
const h = hashId(id)
|
||||
const dLat = ((h % 1600) - 800) / 100000 // ±0.008° ≈ ±0.9km
|
||||
const dLng = (((h >> 8) % 1600) - 800) / 100000
|
||||
return { latitude: userLoc.latitude + dLat, longitude: userLoc.longitude + dLng }
|
||||
}
|
||||
|
||||
// Rough distance text from coordinate delta (fallback when no real distance)
|
||||
function distanceText(petLoc, userLoc) {
|
||||
if (!petLoc || !userLoc) return null
|
||||
const R = 6371000
|
||||
const dLat = ((petLoc.latitude - userLoc.latitude) * Math.PI) / 180
|
||||
const dLon = ((petLoc.longitude - userLoc.longitude) * Math.PI) / 180
|
||||
const a =
|
||||
Math.sin(dLat / 2) ** 2 +
|
||||
Math.cos((userLoc.latitude * Math.PI) / 180) *
|
||||
Math.cos((petLoc.latitude * Math.PI) / 180) *
|
||||
Math.sin(dLon / 2) ** 2
|
||||
const meters = Math.round(R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)))
|
||||
if (meters < 1000) return `${meters}m`
|
||||
return `${(meters / 1000).toFixed(1)}km`
|
||||
}
|
||||
|
||||
exports.main = async event => {
|
||||
const filter = event.filters?.type || 'all'
|
||||
const userLoc = event.location || null
|
||||
const query = {}
|
||||
if (filter === 'dog' || filter === 'cat') query.species = filter
|
||||
if (filter === 'online') query.online = true
|
||||
|
||||
const res = await db.collection('pets').where(query).limit(50).get()
|
||||
|
||||
const list = res.data.map(pet => {
|
||||
const realCoord = pet.location && typeof pet.location.latitude === 'number' ? pet.location : null
|
||||
const coord = realCoord || (userLoc ? syntheticCoord(pet._id, userLoc) : null)
|
||||
return {
|
||||
...pet,
|
||||
latitude: coord ? coord.latitude : undefined,
|
||||
longitude: coord ? coord.longitude : undefined,
|
||||
distanceText: distanceText(coord, userLoc) || pet.distanceText || null,
|
||||
pin: stablePin(pet._id)
|
||||
}
|
||||
})
|
||||
|
||||
return { list }
|
||||
}
|
||||
Reference in New Issue
Block a user