import * as path from "@std/path" import "zx/globals" function getConfigPath() { if (Deno.build.os == "windows") { return `${os.homedir}/AppData/Local/rainwall` } else if (Deno.build.os == "darwin") { return `${os.homedir()}/Library/Preferences/rainwall` } else { return process.env.XDG_CONFIG_HOME ? `${process.env.XDG_CONFIG_HOME}/rainwall` : `${os.homedir()}/.config/rainwall` } } function getCachePath() { if (Deno.build.os == "windows") { return `${os.homedir}/AppData/Local/Temp/rainwall` } else if (Deno.build.os == "darwin") { return `${os.homedir()}/Library/Caches/rainwall` } else { return process.env.XDG_CACHE_HOME ? `${process.env.XDG_CACHE_HOME}/rainwall` : `${os.homedir()}/.cache/rainwall` } } // ensure the config and cache directories exist if (!fs.statSync(path.fromFileUrl(`file:///${getConfigPath()}`), { throwIfNoEntry: false })) { fs.mkdirSync(path.fromFileUrl(`file:///${getConfigPath()}`), { recursive: true }) } if (!fs.statSync(path.fromFileUrl(`file:///${getCachePath()}`), { throwIfNoEntry: false })) { fs.mkdirSync(path.fromFileUrl(`file:///${getCachePath()}`), { recursive: true }) } export const applyConfigPath = path.fromFileUrl(`file:///${getConfigPath()}/apply-config.json`) export const analyzeConfigPath = path.fromFileUrl(`file:///${getConfigPath()}/analyze-config.json`) export const cachePath = path.fromFileUrl(`file:///${getCachePath()}/analysis.json`) export async function loadConfig(pathToConfig: string, defaultConfig: object) { let tries = 0 const maxTries = 3 while (tries < maxTries) { try { const stringConfig = await fs.promises.readFile(`${pathToConfig}`, { encoding: "utf8", }) const config = JSON.parse(stringConfig) console.info(`Loaded config from ${pathToConfig}!`) return config } catch (err) { console.warn(chalkWarn( `Got ${(err as Error).message} when trying to load config, generating a new one... you may need to stop this process and edit the config file.`, )) writeConfig(pathToConfig, defaultConfig) tries++ if (tries == maxTries) throw new Error(`Couldn't read config in ${maxTries} tries`) } } } async function writeConfig(path: string, data: object) { await fs.writeFile(`${path}`, JSON.stringify(data, null, 4)) console.info(`Generated default config at ${path}!`) } export const chalkError = chalk.bold.red export const chalkWarn = chalk.yellow export const chalkDebug = chalk.gray export function clamp(number: number, min: number, max: number) { return Math.max(min, Math.min(number, max)) } export function map(number: number, min: number, max: number, newMin: number, newMax: number) { return ((number - min) / (max - min)) * (newMax - newMin) + newMin } export function easeOutQuint(x: number): number { return 1 - Math.pow(1 - x, 5) } export function mapEased( number: number, min: number, max: number, newMin: number, newMax: number, func: (n: number) => number, ) { return func((number - min) / (max - min)) * (newMax - newMin) + newMin } // Fisher-Yates Shuffle // deno-lint-ignore no-explicit-any export function shuffle(array: any[]) { let currentIndex = array.length // While there remain elements to shuffle... while (currentIndex != 0) { // Pick a remaining element... const randomIndex = Math.floor(Math.random() * currentIndex) currentIndex-- // And swap it with the current element. [array[currentIndex], array[randomIndex]] = [ array[randomIndex], array[currentIndex], ] } return array }