Compare commits

...
3 Commits
Author SHA1 Message Date
Landon Wills 811534adec testing 2025-08-28 05:48:26 -04:00
Landon Wills 242f1f2c97 Add tropius 2025-08-28 04:39:14 -04:00
Landon Wills 2140d5323f Add sound scraping 2025-08-28 04:39:09 -04:00
16 changed files with 718 additions and 197 deletions

No files matched your search

@@ -52,32 +52,35 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/rocket",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "21-40",
"SKILL": "0-20",
"SPEED": "21-40",
"STAMINA": "41-60"
"ACCELERATION": "21-40",
"JUMP": "0-20",
"SKILL": "41-60",
"SPEED": "61-80",
"STAMINA": "21-40"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "0-20",
"SKILL": "21-40",
"SPEED": "0-20",
"STAMINA": "61-80"
"ACCELERATION": "0-20",
"JUMP": "21-40",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "0-20"
}
},
"LIQUID": {
"key": "cobblemon:liquid/boat",
"ridingSounds": [],
"stats": {
"ACCELERATION": "61-80",
"JUMP": "0-20",
"SKILL": "21-40",
"SPEED": "41-60",
"STAMINA": "61-80"
"ACCELERATION": "41-60",
"JUMP": "21-40",
"SKILL": "61-80",
"SPEED": "61-80",
"STAMINA": "0-20"
}
}
},
@@ -53,22 +53,35 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/bird",
"ridingSounds": [
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2))",
"playForNonPassengers": true,
"soundLocation": "cobblemon:ride.loop.leather",
"volumeExpr": "math.pow(math.min(q.ride_velocity() / 1.5, 1.0),2)"
},
{
"soundLocation": "cobblemon:ride.loop.wind"
}
],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "21-40",
"SKILL": "61-80",
"SPEED": "41-60",
"JUMP": "61-80",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "21-40"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "0-20",
"SKILL": "21-40",
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "41-60"
"STAMINA": "0-20"
}
}
},
@@ -477,65 +490,6 @@
"speed": 100
},
"baseExperienceYield": 317,
"riding": {
"behaviour": {
"alternateBehaviour": {
"speed": "Math.clamp(q.entity.velocity.horizontal_magnitude + 0.33, 0, 1)",
"gravity": "q.gravity * (0.1 + (q.passenger_count - 1) * 0.1)",
"jumpVector": [
0,
"0.3*q.jump_strength/50",
0
],
"key": "cobblemon:air/bird"
},
"defaultBehaviour": {
"speed": "Math.clamp(q.entity.velocity.horizontal_magnitude + 0.33, 0, 1)",
"gravity": "q.gravity * (0.1 + (q.passenger_count - 1) * 0.1)",
"jumpVector": [
0,
"0.3*q.jump_strength/50",
"-1 * 0.5*q.jump_strength/50"
],
"key": "cobblemon:land/horse"
},
"key": "cobblemon:composite",
"transitionStrategy": "cobblemon:strategy/jump"
},
"seats": [],
"stats": {
"ACCELERATION": {
"ranges": {
"AIR": "20-50",
"LAND": "90-100"
}
},
"JUMP": {
"ranges": {
"AIR": "25-50",
"LAND": "10-20"
}
},
"SKILL": {
"ranges": {
"AIR": "50-100",
"LAND": "15-30"
}
},
"SPEED": {
"ranges": {
"AIR": "25-60",
"LAND": "10-20"
}
},
"STAMINA": {
"ranges": {
"AIR": "35-70",
"LAND": "15-30"
}
}
}
},
"evolutions": [],
"battleOnly": true,
"dynamaxBlocked": true
@@ -53,22 +53,24 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/hover",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "21-40",
"ACCELERATION": "41-60",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "21-40"
"STAMINA": "41-60"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"JUMP": "41-60",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "21-40"
"STAMINA": "41-60"
}
}
},
@@ -54,22 +54,24 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/bird",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "41-60",
"SPEED": "0-20",
"STAMINA": "41-60"
"ACCELERATION": "0-20",
"JUMP": "41-60",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "21-40"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "21-40",
"ACCELERATION": "0-20",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "0-20",
"STAMINA": "61-80"
"SPEED": "21-40",
"STAMINA": "21-40"
}
}
},
@@ -51,26 +51,15 @@
},
"riding": {
"behaviours": {
"LAND": {
"canJump": false,
"canSprint": false,
"key": "cobblemon:land/horse",
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "21-40"
}
},
"LIQUID": {
"key": "cobblemon:liquid/boat",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "0-20",
"ACCELERATION": "21-40",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "41-60"
"STAMINA": "0-20"
}
}
},
@@ -51,26 +51,15 @@
},
"riding": {
"behaviours": {
"LAND": {
"canJump": false,
"canSprint": false,
"key": "cobblemon:land/horse",
"LIQUID": {
"key": "cobblemon:liquid/boat",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "21-40"
}
},
"LIQUID": {
"key": "cobblemon:liquid/submarine",
"stats": {
"ACCELERATION": "41-60",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "61-80"
"STAMINA": "41-60"
}
}
},
@@ -54,32 +54,35 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/jet",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"ACCELERATION": "61-80",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "61-80",
"STAMINA": "21-40"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"stats": {
"ACCELERATION": "21-40",
"JUMP": "61-80",
"SKILL": "41-60",
"SPEED": "41-60",
"STAMINA": "41-60"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "41-60",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "61-80"
}
},
"LIQUID": {
"key": "cobblemon:liquid/boat",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "0-20",
"SKILL": "41-60",
"SPEED": "0-20",
"STAMINA": "41-60"
"ACCELERATION": "0-20",
"JUMP": "41-60",
"SKILL": "21-40",
"SPEED": "41-60",
"STAMINA": "0-20"
}
}
},
@@ -53,22 +53,35 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/rocket",
"ridingSounds": [
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.driver_input() / 1.5, 1.0),2))",
"playForNonPassengers": true,
"soundLocation": "cobblemon:ride.loop.rocket",
"volumeExpr": "math.pow(math.min((q.driver_input() / 1.5) + (q.ride_velocity() / 1.5), 1.0),2)"
},
{
"soundLocation": "cobblemon:ride.loop.wind"
}
],
"stats": {
"ACCELERATION": "0-20",
"JUMP": "61-80",
"SKILL": "41-60",
"ACCELERATION": "21-40",
"JUMP": "41-60",
"SKILL": "0-20",
"SPEED": "21-40",
"STAMINA": "41-60"
"STAMINA": "61-80"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "0-20",
"ACCELERATION": "21-40",
"JUMP": "41-60",
"SKILL": "41-60",
"SKILL": "0-20",
"SPEED": "21-40",
"STAMINA": "61-80"
"STAMINA": "41-60"
}
}
},
@@ -54,22 +54,24 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/bird",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "61-80",
"ACCELERATION": "61-80",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "61-80",
"STAMINA": "41-60"
"SPEED": "21-40",
"STAMINA": "61-80"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "61-80",
"SKILL": "21-40",
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "21-40"
"STAMINA": "61-80"
}
}
},
@@ -52,12 +52,13 @@
"behaviours": {
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "41-60",
"ACCELERATION": "61-80",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "61-80",
"STAMINA": "81-100"
"SPEED": "21-40",
"STAMINA": "41-60"
}
}
},
@@ -53,22 +53,24 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/bird",
"ridingSounds": [],
"stats": {
"ACCELERATION": "0-20",
"ACCELERATION": "41-60",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "41-60",
"STAMINA": "61-80"
"SKILL": "0-20",
"SPEED": "21-40",
"STAMINA": "21-40"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "21-40",
"SKILL": "0-20",
"SPEED": "21-40",
"STAMINA": "21-40"
"STAMINA": "41-60"
}
}
},
@@ -53,11 +53,12 @@
"behaviours": {
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "61-80",
"JUMP": "41-60",
"SKILL": "41-60",
"SPEED": "41-60",
"SPEED": "21-40",
"STAMINA": "61-80"
}
}
@@ -51,7 +51,7 @@
"riding": {
"behaviours": {
"LAND": {
"key": "cobblemon:land/vehicle",
"key": "cobblemon:land/horse",
"stats": {
"ACCELERATION": "61-80",
"JUMP": "41-60",
@@ -45,6 +45,320 @@
"eggCycles": 20,
"baseFriendship": 50,
"baseScale": 0.9,
"riding": {
"behaviours": {
"LAND": {
"key": "cobblemon:land/horse",
"stats": {
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "21-40"
}
}
},
"seats": [
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseOffsets": [
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"WALK"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"OPEN"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"PROFILE"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"SHOULDER_LEFT"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"SWIM"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"PORTRAIT"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"FLY"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"NONE"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"GLIDE"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"SHOULDER_RIGHT"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"HOVER"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"STAND"
]
},
{
"offset": {
"x": 6.458311E-4,
"y": -0.7845242,
"z": 0.17028669
},
"poseTypes": [
"FLOAT"
]
},
{
"offset": {
"x": -0.020952305,
"y": -0.7691353,
"z": 0.26083404
},
"poseTypes": [
"SLEEP"
]
}
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseOffsets": [
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"WALK"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"OPEN"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"PROFILE"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"SHOULDER_LEFT"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"SWIM"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"PORTRAIT"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"FLY"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"NONE"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"GLIDE"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"SHOULDER_RIGHT"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"HOVER"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"STAND"
]
},
{
"offset": {
"x": -0.0015631126,
"y": -0.7421754,
"z": 1.1267918
},
"poseTypes": [
"FLOAT"
]
},
{
"offset": {
"x": -0.79389423,
"y": -0.7722497,
"z": 0.9370501
},
"poseTypes": [
"SLEEP"
]
}
]
}
]
},
"behaviour": {
"moving": {
"walk": {
+182
View File
@@ -0,0 +1,182 @@
(ns asset-status
(:require
[clojure.java.io :refer [file]]
[clojure.data.json :refer [read-str write-str]]
[clojure.set :as set]
[clj-http.client :as client]
[clojure.data.csv :as csv]
[clojure.string :as s])
(:import
(com.cobblemon.mod.common.api.pokemon PokemonSpecies)
(com.cobblemon.mod.common.client.render.models.blockbench FloatingState)
(com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation BedrockAnimationRepository)
(com.cobblemon.mod.common.client.render.models.blockbench.repository VaryingModelRepository)
(java.util Collection HashSet)
(net.minecraft.resources ResourceLocation)))
(def headers
[:generation :dex-no :species :land-behaviour :liquid-behaviour :air-behaviour :land-speed :land-acceleration
:land-skill :land-jump :land-stamina :liquid-speed :liquid-acceleration :liquid-skill :liquid-jump :liquid-stamina
:air-speed :air-acceleration :air-skill :air-jump :air-stamina])
(defn csv->map
"Takes a series of CSV rows and returns a map of the columns with the header as the key"
[csv-data]
(let [data (drop 3 csv-data)]
(map zipmap (repeat headers) data)))
(defn fetch-csv
"Fetch and parse the riding data CSV"
[]
(let [url "https://docs.google.com/spreadsheets/u/1/d/1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0/export?format=csv&id=1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0&gid=50216943"]
(->> (client/get url)
(:body)
(csv/read-csv)
(csv->map))))
(defn contains-animation? [animation coll]
(boolean (some #(s/ends-with? % animation) coll)))
(defn get-required-animations [riding-style riding-behaviour]
(condp = riding-style
:air #(and (contains-animation? "air_fly" %) (contains-animation? "air_idle" %))
:land (if (= riding-behaviour "Basic")
#(and (contains-animation? "ground_idle" %) (contains-animation? "ground_walk" %))
#(and (contains-animation? "ground_idle" %) (contains-animation? "ground_walk" %) (contains-animation? "ground_run" %)))
:liquid #(or (and (contains-animation? "water_idle" %) (contains-animation? "water_swim" %))
(and (contains-animation? "surfacewater_idle" %) (contains-animation? "surfacewater_swim" %)))))
(defn get-species-form-name [species form]
(if (or (nil? form) (= "Normal" (.getName form)))
(.getName species)
(str (.getName species) " [" (.getName form) "]")))
(def excluded-behaviours #{"Roll" "Climbing" "Burst" "Waterwalking" "Strider" "Airship" "Glider" "N/A" "Submarine"})
(defn has-riding-behaviour? [species form csv behaviour]
(let [csv-data (first (filter #(= (:species %) (get-species-form-name species form)) csv))
not-nil-or-na #(and (not (nil? %)) (not (set/subset? #{%} excluded-behaviours)))]
(if (not csv-data)
false
(not-nil-or-na (get csv-data behaviour)))))
(defn has-riding-behaviours? [species form csv]
(or
(has-riding-behaviour? species form csv :air-behaviour)
(has-riding-behaviour? species form csv :land-behaviour)
(has-riding-behaviour? species form csv :liquid-behaviour)))
(defn needs-riding-animation? [species form riding-style csv]
(let [csv-data (first (filter #(= (:species %) (get-species-form-name species form)) csv))
behaviour (get csv-data (keyword (str (name riding-style) "-behaviour")))
required-animation-fn (get-required-animations riding-style behaviour)]
(if (or (nil? csv-data) (set/subset? #{behaviour} excluded-behaviours))
false
(let [state (FloatingState.)
species-resource-id (.getResourceIdentifier species)]
(when form (.setCurrentAspects state (set (.getAspects form))))
(let [variation (get (.getVariations VaryingModelRepository/INSTANCE) species-resource-id)
resolved-poser (when variation (.getResolvedPoser variation state))
name (when resolved-poser (.getPath resolved-poser))]
(if name
(not (required-animation-fn (.getAnimations BedrockAnimationRepository/INSTANCE name)))
false))))))
(defn has-seat? [species form]
(let [state (FloatingState.)
species-resource-id (.getResourceIdentifier species)]
(when form
(.setCurrentAspects state (set (.getAspects form))))
(let [poser (.getPoser VaryingModelRepository/INSTANCE species-resource-id state)]
(.setCurrentModel state poser)
(.updateLocators poser nil state)
(boolean (some #(s/starts-with? % "seat_") (keys (.getLocatorStates state)))))))
(defn has-variation? [species form]
(let [aspects (.getAspects form)
resolver (-> (.getVariations VaryingModelRepository/INSTANCE) (.get (.getResourceIdentifier species)))
variations (.getVariations resolver)
matching-variation (filter #(= (set aspects) (set (.getAspects %))) variations)]
(not (empty? matching-variation))))
(defn implemented? [species form]
(if (or (nil? form) (= (.getName form) "Default"))
(.getImplemented species)
(and (.getImplemented species) (has-variation? species form))))
(defn create-implemented-map [species form csv]
(let [result-species (.getName species)
result-form (if (nil? form) "Normal" (.getName form))
implemented? (implemented? species form)
has-seat? (has-seat? species form)]
{:species result-species
:form result-form
:implemented? implemented?
:has-riding-behaviours? (has-riding-behaviours? species form csv)
:has-air-behaviour? (has-riding-behaviour? species form csv :air-behaviour)
:has-land-behaviour? (has-riding-behaviour? species form csv :land-behaviour)
:has-liquid-behaviour? (has-riding-behaviour? species form csv :liquid-behaviour)
:has-seat? has-seat?
:needs-air-riding-animations? (needs-riding-animation? species form :air csv)
:needs-land-riding-animations? (needs-riding-animation? species form :land csv)
:needs-liquid-riding-animations? (needs-riding-animation? species form :liquid csv)}))
(defn implemented-status [species csv]
(if (empty? (.getForms species))
[(create-implemented-map species nil csv)]
(map #(create-implemented-map species % csv) (.getForms species))))
(defn get-engineering-data []
(let [csv (fetch-csv)]
(->> (map #(implemented-status % csv) (.getSpecies PokemonSpecies/INSTANCE))
(reduce into []))))
(def results (get-engineering-data))
;
(defn general-stats []
(let [results (get-engineering-data)
total (count results)]
{:total total
:implemented? (count (filter :implemented? results))
:has-seat? (count (filter :has-seat? results))
:has-a-riding-behaviour? (count (filter :has-riding-behaviours? results))
:needs-animations? (count (filter #(or (:needs-air-riding-animations? %)
(:needs-land-riding-animations? %)
(:needs-liquid-riding-animations? %)) results))}))
(def ordered-keys [:species :form :implemented? :has-seat? :has-riding-behaviours? :has-air-behaviour? :needs-air-riding-animations? :has-land-behaviour? :needs-land-riding-animations? :has-liquid-behaviour? :needs-liquid-riding-animations?])
(defn sort-compare [a b]
(let [key->index (zipmap ordered-keys (range))]
(compare (get key->index a) (get key->index b))))
(defn get-engineering-data-csv []
(let [headers ["Species" "Form" "Implemented?" "Has Seat?" "Has Riding Behaviours?" "Has Air Behaviour?" "Needs Air Animations?" "Has Land Behaviour?" "Needs Land Animations?" "Has Liquid Behaviour?" "Needs Liquid Animations?"]]
(->> (get-engineering-data)
(map #(into (sorted-map-by sort-compare) %))
(sort-by (juxt :species :form))
(map #(s/join "," (vals %)))
(s/join "\n")
(str (s/join "," headers) "\n")
(spit "output.csv"))))
(defn get-engineering-data-csv []
(let [headers ["Species" "Form" "Implemented?" "Has Seat?" "Has Riding Behaviours?" "Has Air Behaviour?" "Needs Air Animations?" "Has Land Behaviour?" "Needs Land Animations?" "Has Liquid Behaviour?" "Needs Liquid Animations?"]]
(->> (get-engineering-data)
(map #(into (sorted-map-by sort-compare) %))
(sort-by (juxt :species :form)))))
(defn ready-to-scrape? [data]
(and (:implemented? data)
(not (:has-seat? data))
(:has-riding-behaviours? data)
(or (not (:has-air-behaviour? data)) (not (:needs-air-riding-animations? data)))
(or (not (:has-land-behaviour? data)) (not (:needs-land-riding-animations? data)))
(or (not (:has-liquid-behaviour? data)) (not (:needs-liquid-riding-animations? data)))))
(let [headers ["Species" "Form" "Implemented?" "Has Seat?" "Has Riding Behaviours?" "Has Air Behaviour?" "Needs Air Animations?" "Has Land Behaviour?" "Needs Land Animations?" "Has Liquid Behaviour?" "Needs Liquid Animations?"]
data (->> (get-engineering-data)
(map #(into (sorted-map-by sort-compare) %))
(sort-by (juxt :species :form))
(filter ready-to-scrape?))]
(map #(select-keys % [:species :form]) data))
+91 -27
View File
@@ -58,9 +58,10 @@
(into {} (map (fn [x] [x (get-seat-locator state x)]) seat-locators))))))
(def headers
[:generation :dex-no :species :land-behaviour :liquid-behaviour :air-behaviour :land-speed :land-acceleration
:land-skill :land-jump :land-stamina :liquid-speed :liquid-acceleration :liquid-skill :liquid-jump :liquid-stamina
:air-speed :air-acceleration :air-skill :air-jump :air-stamina])
[:generation :dex-no :species :land-behaviour :liquid-behaviour :air-behaviour :land-ready-to-scrape?
:liquid-ready-to-scrape? :air-ready-to-scrape? :land-speed :land-acceleration :land-skill :land-jump
:land-stamina :liquid-speed :liquid-acceleration :liquid-skill :liquid-jump :liquid-stamina :air-speed
:air-acceleration :air-skill :air-jump :air-stamina])
(def behaviour-keys
{"Jet" "cobblemon:air/jet"
@@ -86,8 +87,8 @@
(defn csv->map
"Takes a series of CSV rows and returns a map of the columns with the header as the key"
[csv-data]
(let [data (drop 3 csv-data)]
[csv-data headers start]
(let [data (drop start csv-data)]
(map zipmap (repeat headers) data)))
(defn concat-keyword
@@ -105,7 +106,7 @@
=> {:air {:behaviour \"Boat\" :skills {:speed \"B\"}}
"
[data type]
(if (= "N/A" (get data (concat-keyword type "behaviour")))
(if (or (not (= "Yes" (get data (concat-keyword type "ready-to-scrape?")))) (= "N/A" (get data (concat-keyword type "behaviour"))))
data
(assoc data (keyword type)
{:behaviour (get data (concat-keyword type "behaviour"))
@@ -197,11 +198,50 @@
(defn fetch-csv
"Fetch and parse the riding data CSV"
[]
(let [url "https://docs.google.com/spreadsheets/u/1/d/1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0/export?format=csv&id=1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0&gid=50216943"]
(->> (client/get url)
(let [riding-stat-url "https://docs.google.com/spreadsheets/u/1/d/1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0/export?format=csv&id=1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0&gid=50216943"]
(->> (client/get riding-stat-url)
(:body)
(csv/read-csv))))
(defn get-sound-mappings []
(let [data (->> (client/get "https://docs.google.com/spreadsheets/u/1/d/1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0/export?format=csv&id=1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0&gid=513653624")
(:body)
(csv/read-csv)
(rest)
(into {}))]
(update-vals data #(read-str % :key-fn keyword))))
(def sound-headers
[:generation :dex-no :species
:land-riding-sound-1 :land-riding-sound-2 :land-riding-sound-3 :land-riding-sound-4 :land-riding-sound-5
:liquid-riding-sound-1 :liquid-riding-sound-2 :liquid-riding-sound-3 :liquid-riding-sound-4 :liquid-riding-sound-5
:air-riding-sound-1 :air-riding-sound-2 :air-riding-sound-3 :air-riding-sound-4 :air-riding-sound-5])
(defn get-sounds []
(->> (client/get "https://docs.google.com/spreadsheets/u/1/d/1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0/export?format=csv&id=1YhQlnH6m-tlkVbopIg5KLV8BFaaDCgZNkx3dIAy5PZ0&gid=1378925558")
(:body)
(csv/read-csv)
(#(csv->map % sound-headers 3))
(map #(merge % (name->species-form (:species %))))
(map #(assoc % :form (or (:form %) "Normal")))))
(defn condense-sound-type [sound-data sound-mappings riding-type]
(let [keys (map #(concat-keyword riding-type (str "riding-sound-" %)) [1 2 3 4 5])
values (vec (filter not-empty (map #(get sound-data %) keys)))
json (map #(get sound-mappings %) values)]
(vec json)))
(defn sound-data->json [sound-mappings sound-data riding-type]
(->> (map #(assoc % :sound-json (condense-sound-type % sound-mappings riding-type)) sound-data)
(map (fn [x] {[(:species x) (:form x)] x}))
(apply merge)
(#(update-vals % :sound-json))))
(defn get-sounds-map [sound-mappings sounds]
(->> ["air" "liquid" "land"]
(map (fn [x] [x (sound-data->json sound-mappings sounds x)]))
(into {})))
(defn stats->json
"Builds a JSON-ready map of riding stat grades from the provided stats-data."
[stats-data]
@@ -242,13 +282,13 @@
- Expects `behaviour-data` like {:behaviour \"...\" :stats {:speed \"A\" ...}}.
- Resolves a stable key via `behaviour-keys`; returns nil if behaviour is unknown.
- Translates letter grades to numeric ranges via `grade-ranges`."
[behaviour-data]
[behaviour-data behaviour-sounds]
(let [behaviour (:behaviour behaviour-data)
behaviour-json (behaviour-type->json behaviour)
stats (:stats behaviour-data)
stats-json (stats->json stats)]
(when (and behaviour-json stats-json)
(merge behaviour-json stats-json))))
(merge behaviour-json stats-json behaviour-sounds))))
(defn assoc-behaviour
"Conditionally assoc a behaviour block into the accumulator `map`.
@@ -256,9 +296,10 @@
- `behaviour` is the keyword to read (e.g., :air).
- When present and valid, associates under an upper-cased key (e.g., :AIR).
Returns the updated map or the original map if nothing was added."
[map species-data behaviour]
(let [behaviour-data (get species-data behaviour)
behaviour-json (behaviour->json behaviour-data)]
[map species-data behaviour sounds]
(let [behaviour-sounds (get-in sounds [(name behaviour) [(:species species-data) (or (:form species-data) "Normal")]])
behaviour-data (get species-data behaviour)
behaviour-json (behaviour->json behaviour-data {:ridingSounds behaviour-sounds})]
(if (and behaviour-data behaviour-json)
(assoc map (keyword (upper-case (name behaviour))) behaviour-json)
map)))
@@ -306,12 +347,12 @@
"Assemble the behaviours section for a species in the expected JSON schema.
Builds a map of available behaviours (:AIR, :LAND, :LIQUID) using `assoc-behaviour`.
Wraps the result as {:riding {:behaviours {...}}}. Returns nil when no behaviours exist."
[species-data]
[species-data sounds]
(let [behaviours
(-> {}
(assoc-behaviour species-data :air)
(assoc-behaviour species-data :land)
(assoc-behaviour species-data :liquid))]
(assoc-behaviour species-data :air sounds)
(assoc-behaviour species-data :land sounds)
(assoc-behaviour species-data :liquid sounds))]
(when (not-empty behaviours)
{:riding {:behaviours behaviours
:seats (seats->json (:seat-data species-data))}})))
@@ -319,7 +360,10 @@
(defn sanitize-species-name
"Normalizes `species` by lower-casing and removing spaces, underscores, colons, dots, and hyphens."
[species]
(s/replace (lower-case species) #"([ _:\.\-]+)" ""))
(-> species
(lower-case)
(s/replace #"([ _:\.\-']+)" "")
(s/replace "é" "e")))
(defn get-file-for-species
"Return the first JSON file from `files` whose name matches `species`.
@@ -365,11 +409,30 @@
Returns the sanitized JSON map."
[json-data]
(-> json-data
(dissoc-in [:riding :behaviours])
(dissoc-in [:riding :behaviour])
(dissoc-in [:riding :stats])
(dissoc-in [:riding :seats])))
(defn reconcile-riding-sounds [a b]
(update b :behaviours
(fn [b-behaviours]
(reduce-kv
(fn [acc k b-entry]
(let [a-sounds (get-in a [:behaviours k :ridingSounds])
b-sounds (:ridingSounds b-entry)]
(if (seq b-sounds)
(let [a-by-loc (into {} (map (juxt :soundLocation identity) a-sounds))
b-by-loc (into {} (map (juxt :soundLocation identity) b-sounds))
;; keep sounds that exist in both (from A) + sounds only in B
merged (concat
(vals (select-keys a-by-loc (keys b-by-loc))) ; from A
(vals (apply dissoc b-by-loc (keys a-by-loc))))] ; only B
(assoc-in acc [k :ridingSounds] (vec merged)))
;; if B has no sounds, just skip
(assoc acc k b-entry))))
{}
b-behaviours))))
(defn apply-riding-data
"Apply computed `riding-data` to an existing species JSON structure.
- First sanitizes old/legacy riding fields.
@@ -381,14 +444,14 @@
(if form
(assoc sanitized-json-data :forms (map #(if (= (:name %) form) (apply-riding-data % riding-data nil) %) (:forms sanitized-json-data)))
(let [old-riding-json-data (:riding sanitized-json-data)
new-riding-json-data (get-in riding-data [:riding])]
(assoc sanitized-json-data :riding (merge old-riding-json-data new-riding-json-data))))))
new-riding-json-data (reconcile-riding-sounds old-riding-json-data (get-in riding-data [:riding]))]
(assoc sanitized-json-data :riding (deep-merge old-riding-json-data new-riding-json-data))))))
(def sort-order
[:implemented :nationalPokedexNumber :name :primaryType :secondaryType :maleRatio :height :weight
:pokedex :labels :aspects :abilities :eggGroups :baseStats :evYield :baseExperienceYield :experienceGroup :catchRate
:eggCycles :baseFriendship :baseScale :hitbox :riding :behaviour :drops :moves :preEvolution :evolutions
:forms :hp :attack :defence :special_attack :special_defence :speed])
:forms :hp :attack :defence :special_attack :special_defence :speed :key :ridingSounds])
(defn key-comparator
"Create a comparator for map keys using a preferred order.
@@ -475,14 +538,14 @@
- Collapse the data into just the file and new updates, and group results by :file.
- Merge all updates into a single text blob
Returns a map: java.io.File -> string"
[csv files]
[csv files sounds]
(let [file-updates (->> csv
(csv->map)
(#(csv->map % headers 3))
(map sanitize-riding-data)
(filter #(or (:air %) (:land %) (:liquid %)))
(map #(assoc % :seat-data (generate-seat-data %)))
(filter #(:seat-data %))
(map #(assoc % :json (behaviours->json %)))
(map #(assoc % :json (behaviours->json % sounds)))
(filter #(:json %))
(map #(riding-data->cobblemon-json % files))
(group-by :file))]
@@ -491,8 +554,9 @@
(defn run-script []
(let [path "../../common/src/main/resources/data/cobblemon/species"
files (file-seq (file path))
csv (fetch-csv)
updates (get-file-updates csv files)]
riding-data-csv (fetch-csv)
sounds (get-sounds-map (get-sound-mappings) (get-sounds))
updates (get-file-updates riding-data-csv files sounds)]
(doseq [[file contents] updates]
(spit file contents))))