Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@
"battles": false,
"gmaxStationed": false,
"interactionRanges": false,
"customRange": 0
"customRange": 0,
"inactiveStations": false
},
"s2cells": {
"enabled": false,
Expand Down
3 changes: 3 additions & 0 deletions packages/locales/lib/human/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
"total_cp": "Total CP",
"first_seen": "First Seen",
"last_seen": "Last Seen",
"last_active": "Last active: {{time}}",
"last_modified": "Last Modified",
"last_updated": "Last Updated",
"imported": "Imported",
Expand Down Expand Up @@ -815,6 +816,7 @@
"global_search_stations": "Enter Power Spot Name or Dynamax Pokémon...",
"station_timers": "Power Spot Timers",
"stations_opacity": "Dynamic Power Spot Opacity",
"inactive_stations": "Inactive Power Spots",
"max_battles": "Max Battles",
"dynamax": "Dynamax",
"stations_subtitle": "Displays Power Spots on the map",
Expand All @@ -832,6 +834,7 @@
"filters": "Filters",
"active": "Active",
"inactive": "Inactive",
"inactive_since": "Inactive since {{time}}",
"bread_time_window": "You can take on Max Battles between 6AM and 9PM.",
"rsvp_0": "no rsvp",
"rsvp_1": "rsvp",
Expand Down
3 changes: 3 additions & 0 deletions server/src/filters/builder/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ function buildDefaultFilters(perms) {
gmaxStationed: perms.dynamax
? defaultFilters.stations.gmaxStationed
: undefined,
inactiveStations: perms.stations
? defaultFilters.stations.inactiveStations
: undefined,
}
: undefined,
pokemon:
Expand Down
60 changes: 39 additions & 21 deletions server/src/models/Station.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Station extends Model {
onlyMaxBattles,
onlyBattleTier,
onlyGmaxStationed,
onlyInactiveStations,
} = args.filters
const ts = getEpoch()
const select = [
Expand All @@ -54,13 +55,21 @@ class Station extends Model {
maxLon: args.maxLon,
},
})
query
.andWhere('end_time', '>', ts)
.andWhere(
'updated',
'>',
Date.now() / 1000 - stationUpdateLimit * 60 * 60,
)
const activeCutoff = Date.now() / 1000 - stationUpdateLimit * 60 * 60

if (onlyInactiveStations) {
query.andWhere((builder) => {
builder
.where((active) =>
active
.where('end_time', '>', ts)
.andWhere('updated', '>', activeCutoff),
)
.orWhere('end_time', '<=', ts)
})
} else {
query.andWhere('end_time', '>', ts).andWhere('updated', '>', activeCutoff)
}
// .where('is_inactive', false)

if (perms.dynamax && (onlyMaxBattles || onlyGmaxStationed)) {
Expand Down Expand Up @@ -132,10 +141,8 @@ class Station extends Model {
if (!getAreaSql(query, areaRestrictions, onlyAreas, isMad)) {
return []
}
/** @type {import("@rm/types").FullStation[]} */
const results = await query.select(select)

return results
return (await query.select(select))
.map((station) => {
if (station.is_battle_available && station.battle_pokemon_id === null) {
station.is_battle_available = false
Expand All @@ -160,19 +167,30 @@ class Station extends Model {
}
return station
})
.filter(
(station) =>
onlyAllStations ||
(perms.dynamax &&
((onlyMaxBattles &&
(onlyBattleTier === 'all'
? args.filters[`j${station.battle_level}`] ||
.filter((station) => {
if (Number.isFinite(station.end_time) && station.end_time <= ts) {
return onlyInactiveStations
}

const matchesBattleFilter =
onlyMaxBattles &&
(onlyBattleTier === 'all'
? Boolean(
args.filters[`j${station.battle_level}`] ||
args.filters[
`${station.battle_pokemon_id}-${station.battle_pokemon_form}`
]
: onlyBattleTier === station.battle_level)) ||
(onlyGmaxStationed && station.total_stationed_gmax))),
)
],
Comment thread
Mygod marked this conversation as resolved.
Outdated
)
: onlyBattleTier === station.battle_level)

const matchesGmaxFilter =
onlyGmaxStationed && station.total_stationed_gmax > 0

return (
onlyAllStations ||
(perms.dynamax && (matchesBattleFilter || matchesGmaxFilter))
)
})
}

/**
Expand Down
1 change: 1 addition & 0 deletions server/src/ui/drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function drawer(req, perms) {
allStations: perms.stations || BLOCKED,
maxBattles: perms.dynamax || BLOCKED,
gmaxStationed: perms.dynamax || BLOCKED,
inactiveStations: perms.stations || BLOCKED,
}
: BLOCKED,
pokemon:
Expand Down
38 changes: 31 additions & 7 deletions src/features/station/StationPopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -355,17 +355,41 @@ function StationAttackBonus({ total_stationed_pokemon, total_stationed_gmax }) {

/** @param {import('@rm/types').Station} station */
function StationContent({ start_time, end_time, battle_end, id }) {
const { t } = useTranslation()
const dateFormatter = useFormatStore((s) => s.dateFormat)
const now = Date.now() / 1000
const isFutureStart = start_time > now
const hasEndTime = Number.isFinite(end_time)
const endEpoch = hasEndTime ? end_time : 0
const isInactive = hasEndTime && endEpoch < now
const inactiveRelativeTime = useRelativeTimer(endEpoch || 0)

if (isInactive) {
const formatted = dateFormatter.format(new Date(endEpoch * 1000))
return (
<CardContent sx={{ p: 0 }}>
<Stack alignItems="center" justifyContent="center">
<Typography variant="subtitle2">
{t('inactive_since', { time: inactiveRelativeTime })}
</Typography>
<Typography variant="caption">
{t('last_active', { time: formatted })}
</Typography>
</Stack>
</CardContent>
)
}

const hasStartTime = Number.isFinite(start_time)
const startEpoch = hasStartTime ? start_time : 0
const isFutureStart = hasStartTime && startEpoch > now
const displayInactiveOnly =
Number.isFinite(battle_end) &&
Number.isFinite(end_time) &&
battle_end === end_time
Number.isFinite(battle_end) && hasEndTime && battle_end === endEpoch
const epoch = displayInactiveOnly
? (end_time ?? 0)
? endEpoch
: isFutureStart
? (start_time ?? 0)
: (end_time ?? 0)
? startEpoch
: endEpoch

return (
<CardContent sx={{ p: 0 }}>
<Stack alignItems="center" justifyContent="center">
Expand Down
14 changes: 11 additions & 3 deletions src/features/station/useStationMarker.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ export function useStationMarker({
start_time,
end_time,
}) {
const now = Date.now() / 1000
const isInactive = Number.isFinite(end_time) && end_time < now
const hasStarted = Number.isFinite(start_time) && start_time < now
Comment thread
Mygod marked this conversation as resolved.
const [, Icons] = useStorage(
(s) => [s.icons, useMemory.getState().Icons],
(a, b) => Object.entries(a[0]).every(([k, v]) => b[0][k] === v),
)
const [baseIcon, baseSize, battleIcon, battleSize] = useStorage((s) => {
const { filter } = s.filters.stations
return [
Icons.getStation(start_time < Date.now() / 1000),
Icons.getStation(isInactive ? false : hasStarted),
Icons.getSize('station', filter[`j${battle_level}`]?.size),
Icons.getPokemon(
battle_pokemon_id,
Expand All @@ -47,8 +50,13 @@ export function useStationMarker({
]
}, basicEqualFn)
const [stationMod, battleMod] = Icons.getModifiers('station', 'dynamax')
const opacity = useOpacity('stations')(end_time)
const isActive = !!battle_pokemon_id && start_time < Date.now() / 1000
const dynamicOpacity = useOpacity('stations')(end_time)
const opacity = isInactive ? 0.3 : dynamicOpacity
const isActive =
!isInactive &&
!!battle_pokemon_id &&
Number.isFinite(start_time) &&
start_time < now
Comment thread
Mygod marked this conversation as resolved.

return divIcon({
popupAnchor: [
Expand Down
20 changes: 15 additions & 5 deletions src/pages/map/components/QueryData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,22 @@ const trimFilters = (requestedFilters, userSettings, category, onlyAreas) => {
onlyAllPvp: userSettings?.showAllPvpRanks,
onlyAreas: onlyAreas || [],
}
Object.entries(requestedFilters || {}).forEach((topLevelFilter) => {
const [id, specifics] = topLevelFilter

if (!FILTER_SKIP_LIST.includes(id)) {
trimmed[`only${id.charAt(0).toUpperCase()}${id.slice(1)}`] = specifics
const applyTopLevelFilter = (id, specifics) => {
if (FILTER_SKIP_LIST.includes(id)) return
const trimmedKey = `only${id.charAt(0).toUpperCase()}${id.slice(1)}`
if (typeof specifics === 'boolean') {
if (specifics) {
trimmed[trimmedKey] = true
}
return
}
if (specifics !== undefined) {
trimmed[trimmedKey] = specifics
}
}

Object.entries(requestedFilters || {}).forEach(([id, specifics]) => {
applyTopLevelFilter(id, specifics)
})
Object.entries(userSettings || {}).forEach(([entryK, entryV]) => {
if (entryK.startsWith('pvp')) {
Expand Down
1 change: 1 addition & 0 deletions src/pages/map/hooks/usePermCheck.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function usePermCheck(category) {
case 'stations':
if (
(filters?.allStations && perms?.stations) ||
(filters?.inactiveStations && perms?.stations) ||
(filters?.maxBattles && perms?.dynamax) ||
(filters?.gmaxStationed && perms?.dynamax)
) {
Expand Down
Loading