Imagery imported for icons and items. Live updates working.
Hover tooltip working. Features.md added for better tracking.
This commit is contained in:
147
os-league-tools-master/src/utils/apiTransformers.js
Normal file
147
os-league-tools-master/src/utils/apiTransformers.js
Normal file
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Transformers to convert Spring backend API responses into frontend data format
|
||||
*/
|
||||
|
||||
import { SKILL_NAMES } from '../models/Skill';
|
||||
|
||||
/**
|
||||
* Transform skills array from API (24 XP values) into object
|
||||
* @param {Array<number>} skillsArray - Array of 24 XP values
|
||||
* @returns {Object} Skills object with skill names as keys
|
||||
*/
|
||||
export function transformSkills(skillsArray) {
|
||||
if (!skillsArray || !Array.isArray(skillsArray)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const skills = {};
|
||||
SKILL_NAMES.forEach((skillName, index) => {
|
||||
if (index < skillsArray.length) {
|
||||
skills[skillName] = skillsArray[index];
|
||||
}
|
||||
});
|
||||
|
||||
// Add Overall (total XP)
|
||||
skills.Overall = skillsArray.reduce((sum, xp) => sum + xp, 0);
|
||||
|
||||
return skills;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform stats array from API into structured object
|
||||
* API format: [hp_current, hp_max, prayer_current, prayer_max, energy_current, energy_max, world]
|
||||
* @param {Array<number>} statsArray - Array of 7 integers
|
||||
* @returns {Object} Stats object
|
||||
*/
|
||||
export function transformStats(statsArray) {
|
||||
if (!statsArray || !Array.isArray(statsArray) || statsArray.length < 7) {
|
||||
return {
|
||||
hitpoints: { current: 10, max: 10 },
|
||||
prayer: { current: 1, max: 1 },
|
||||
energy: { current: 10000, max: 10000 },
|
||||
world: null,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
hitpoints: {
|
||||
current: statsArray[0],
|
||||
max: statsArray[1],
|
||||
},
|
||||
prayer: {
|
||||
current: statsArray[2],
|
||||
max: statsArray[3],
|
||||
},
|
||||
energy: {
|
||||
current: statsArray[4],
|
||||
max: statsArray[5],
|
||||
},
|
||||
world: statsArray[6] || null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform inventory/equipment array from API into item objects
|
||||
* API format: flat array alternating [id1, quantity1, id2, quantity2, ...]
|
||||
* @param {Array<number>} itemsArray - Flat array of item data
|
||||
* @returns {Array<Object>} Array of {id, quantity} objects
|
||||
*/
|
||||
export function transformItems(itemsArray) {
|
||||
if (!itemsArray || !Array.isArray(itemsArray)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const items = [];
|
||||
for (let i = 0; i < itemsArray.length; i += 2) {
|
||||
items.push({
|
||||
id: itemsArray[i] || 0,
|
||||
quantity: itemsArray[i + 1] || 0,
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform coordinates array from API
|
||||
* API format: [x, y, plane]
|
||||
* @param {Array<number>} coordsArray - Array of 3 integers
|
||||
* @returns {Object|null} Coordinates object or null
|
||||
*/
|
||||
export function transformCoordinates(coordsArray) {
|
||||
if (!coordsArray || !Array.isArray(coordsArray) || coordsArray.length < 3) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
x: coordsArray[0],
|
||||
y: coordsArray[1],
|
||||
plane: coordsArray[2],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform full member data from API response
|
||||
* @param {Object} memberData - Raw member data from API
|
||||
* @returns {Object} Transformed member data
|
||||
*/
|
||||
export function transformMemberData(memberData) {
|
||||
if (!memberData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
name: memberData.name,
|
||||
skills: transformSkills(memberData.skills),
|
||||
stats: transformStats(memberData.stats),
|
||||
inventory: transformItems(memberData.inventory),
|
||||
equipment: transformItems(memberData.equipment),
|
||||
bank: transformItems(memberData.bank),
|
||||
runePouch: transformItems(memberData.rune_pouch),
|
||||
seedVault: transformItems(memberData.seed_vault),
|
||||
coordinates: transformCoordinates(memberData.coordinates),
|
||||
interacting: memberData.interacting,
|
||||
last_updated: memberData.last_updated,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform array of members from API response
|
||||
* @param {Array<Object>} membersArray - Array of member data from API
|
||||
* @returns {Array<Object>} Array of transformed member data
|
||||
*/
|
||||
export function transformMembersData(membersArray) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('transformMembersData - input:', membersArray);
|
||||
|
||||
if (!Array.isArray(membersArray)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('transformMembersData - not an array!');
|
||||
return [];
|
||||
}
|
||||
|
||||
const transformed = membersArray.map(transformMemberData).filter(Boolean);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('transformMembersData - output:', transformed);
|
||||
|
||||
return transformed;
|
||||
}
|
||||
82
os-league-tools-master/src/utils/formatters.js
Normal file
82
os-league-tools-master/src/utils/formatters.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Formatting utilities for numbers, quantities, and time
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format large quantities into short strings (1.5K, 2.3M, 1B)
|
||||
* @param {number} quantity - The quantity to format
|
||||
* @returns {string} Formatted string
|
||||
*/
|
||||
export function formatShortQuantity(quantity) {
|
||||
if (quantity < 1000) {
|
||||
return quantity.toString();
|
||||
}
|
||||
if (quantity < 1000000) {
|
||||
const k = Math.floor(quantity / 100) / 10;
|
||||
return `${k}K`;
|
||||
}
|
||||
if (quantity < 1000000000) {
|
||||
const m = Math.floor(quantity / 100000) / 10;
|
||||
return `${m}M`;
|
||||
}
|
||||
const b = Math.floor(quantity / 100000000) / 10;
|
||||
return `${b}B`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format very large quantities into very short strings (1K, 2M, 1B)
|
||||
* @param {number} quantity - The quantity to format
|
||||
* @returns {string} Formatted string
|
||||
*/
|
||||
export function formatVeryShortQuantity(quantity) {
|
||||
if (quantity < 1000) {
|
||||
return quantity.toString();
|
||||
}
|
||||
if (quantity < 1000000) {
|
||||
return `${Math.floor(quantity / 1000)}K`;
|
||||
}
|
||||
if (quantity < 1000000000) {
|
||||
return `${Math.floor(quantity / 1000000)}M`;
|
||||
}
|
||||
return `${Math.floor(quantity / 1000000000)}B`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time since last update
|
||||
* @param {Date|string|number} lastUpdated - Last update timestamp
|
||||
* @returns {string} Formatted string like "2m ago" or "1h ago"
|
||||
*/
|
||||
export function timeSinceLastUpdate(lastUpdated) {
|
||||
const date = lastUpdated instanceof Date ? lastUpdated : new Date(lastUpdated);
|
||||
const now = new Date();
|
||||
const secondsAgo = Math.floor((now - date) / 1000);
|
||||
|
||||
if (secondsAgo < 60) {
|
||||
return `${secondsAgo}s ago`;
|
||||
}
|
||||
if (secondsAgo < 3600) {
|
||||
return `${Math.floor(secondsAgo / 60)}m ago`;
|
||||
}
|
||||
if (secondsAgo < 86400) {
|
||||
return `${Math.floor(secondsAgo / 3600)}h ago`;
|
||||
}
|
||||
return `${Math.floor(secondsAgo / 86400)}d ago`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove articles from string
|
||||
* @param {string} str - String to process
|
||||
* @returns {string} String with articles removed
|
||||
*/
|
||||
export function removeArticles(str) {
|
||||
return str.replace(/^(a|an|the)\s+/i, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Format number with commas
|
||||
* @param {number} num - Number to format
|
||||
* @returns {string} Formatted number
|
||||
*/
|
||||
export function formatNumber(num) {
|
||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
}
|
||||
Reference in New Issue
Block a user