initial commit
This commit is contained in:
259
db_parser.js
Normal file
259
db_parser.js
Normal file
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* Parser for FFXI Trust character data from PostgreSQL database
|
||||
*/
|
||||
|
||||
class TrustParser {
|
||||
constructor() {
|
||||
this.roles = [];
|
||||
this.characters = {};
|
||||
this.charactersByRole = {};
|
||||
this.allCharacters = [];
|
||||
this.dbConfig = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the database configuration
|
||||
*/
|
||||
async initDbConfig() {
|
||||
try {
|
||||
// Try to read from environment variables first (for Docker deployment)
|
||||
if (window.ENV && window.ENV.PSQL_HOST) {
|
||||
console.log('Using database configuration from environment variables');
|
||||
this.dbConfig = {
|
||||
PSQL_USER: window.ENV.PSQL_USER,
|
||||
PSQL_HOST: window.ENV.PSQL_HOST,
|
||||
PSQL_DBNAME: window.ENV.PSQL_DBNAME,
|
||||
PSQL_PASSWORD: window.ENV.PSQL_PASSWORD,
|
||||
PSQL_PORT: window.ENV.PSQL_PORT || '5432',
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fall back to db.conf file
|
||||
console.log('Reading database configuration from db.conf file');
|
||||
const response = await fetch('db.conf');
|
||||
const text = await response.text();
|
||||
|
||||
// Parse the db.conf file
|
||||
const dbConfig = {};
|
||||
text.split('\n').forEach(line => {
|
||||
if (line.trim() === '') return;
|
||||
|
||||
const [key, value] = line.split('=');
|
||||
if (key && value) {
|
||||
// Remove quotes if present
|
||||
const cleanValue = value.replace(/^['"]|['"]$/g, '');
|
||||
dbConfig[key] = cleanValue;
|
||||
}
|
||||
});
|
||||
|
||||
this.dbConfig = dbConfig;
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error loading database configuration:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the data from the database
|
||||
* @param {Array} data - Array of character objects from the database
|
||||
*/
|
||||
processData(data) {
|
||||
// Extract unique roles
|
||||
const roleSet = new Set();
|
||||
data.forEach(char => {
|
||||
if (char.role && char.role.trim()) {
|
||||
roleSet.add(char.role.trim());
|
||||
}
|
||||
});
|
||||
|
||||
this.roles = Array.from(roleSet);
|
||||
|
||||
// Initialize charactersByRole
|
||||
this.roles.forEach(role => {
|
||||
this.charactersByRole[role] = [];
|
||||
});
|
||||
|
||||
// Process each character
|
||||
data.forEach(char => {
|
||||
// Create a character object with normalized property names
|
||||
const character = {
|
||||
id: char.id,
|
||||
name: char.name,
|
||||
altName: char.alt_name || '',
|
||||
role: char.role || 'Unknown',
|
||||
job: char.job || '',
|
||||
spells: char.spells || '',
|
||||
abilities: char.abilities || '',
|
||||
weaponSkills: char.weapon_skills || '',
|
||||
invincible: char.invincible || false,
|
||||
acquisition: char.acquisition || '',
|
||||
specialFeatures: char.special_features || '',
|
||||
trustSynergy: char.trust_synergy || '',
|
||||
trustSynergyNames: char.trust_synergy_names || [],
|
||||
acquired: char.acquired || false
|
||||
};
|
||||
|
||||
// Add to characters object
|
||||
this.characters[char.name] = character;
|
||||
|
||||
// Add to charactersByRole
|
||||
if (character.role && this.charactersByRole[character.role]) {
|
||||
this.charactersByRole[character.role].push(character.name);
|
||||
}
|
||||
|
||||
// Add to allCharacters
|
||||
this.allCharacters.push({
|
||||
name: character.name,
|
||||
role: character.role
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load data from the database
|
||||
* @param {Function} callback - Function to call when loading is complete
|
||||
*/
|
||||
async loadData(callback) {
|
||||
try {
|
||||
// Initialize database configuration if not already done
|
||||
if (!this.dbConfig) {
|
||||
const success = await this.initDbConfig();
|
||||
if (!success) {
|
||||
throw new Error('Failed to initialize database configuration');
|
||||
}
|
||||
}
|
||||
|
||||
// Create the API endpoint URL
|
||||
const apiUrl = `/api/trusts`;
|
||||
|
||||
// Fetch data from the API
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`API request failed with status ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Process the data
|
||||
this.processData(data);
|
||||
|
||||
// Call the callback with the processed data
|
||||
if (callback) {
|
||||
callback({
|
||||
roles: this.roles,
|
||||
characters: this.characters,
|
||||
charactersByRole: this.charactersByRole,
|
||||
allCharacters: this.allCharacters
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading trust data:', error);
|
||||
|
||||
// Fallback to JSON file if database connection fails
|
||||
console.log('Falling back to JSON file...');
|
||||
this.loadFromJson(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback method to load data from JSON file
|
||||
* @param {Function} callback - Function to call when loading is complete
|
||||
*/
|
||||
loadFromJson(callback) {
|
||||
fetch('trusts.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.processData(data);
|
||||
|
||||
// Call the callback with the processed data
|
||||
if (callback) {
|
||||
callback({
|
||||
roles: this.roles,
|
||||
characters: this.characters,
|
||||
charactersByRole: this.charactersByRole,
|
||||
allCharacters: this.allCharacters
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading trust data from JSON:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for characters by name or other attributes
|
||||
* @param {string} query - Search query
|
||||
* @returns {Array} - Array of matching characters
|
||||
*/
|
||||
searchCharacters(query) {
|
||||
if (!query) return this.allCharacters;
|
||||
|
||||
query = query.toLowerCase();
|
||||
|
||||
return this.allCharacters.filter(char => {
|
||||
const character = this.characters[char.name];
|
||||
|
||||
// Search by name
|
||||
if (char.name.toLowerCase().includes(query)) return true;
|
||||
|
||||
// Search by alt_name
|
||||
if (character.altName && character.altName.toLowerCase().includes(query)) return true;
|
||||
|
||||
// Search by role
|
||||
if (char.role.toLowerCase().includes(query)) return true;
|
||||
|
||||
// Search by job
|
||||
if (character.job && character.job.toLowerCase().includes(query)) return true;
|
||||
|
||||
// Search by abilities
|
||||
if (character.abilities && character.abilities.toLowerCase().includes(query)) return true;
|
||||
|
||||
// Search by spells
|
||||
if (character.spells && character.spells.toLowerCase().includes(query)) return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the acquired status of a character
|
||||
* @param {number} id - The ID of the character to toggle
|
||||
* @returns {Promise<Object>} - The updated character
|
||||
*/
|
||||
async toggleAcquired(id) {
|
||||
try {
|
||||
// Create the API endpoint URL
|
||||
const apiUrl = `/api/trusts/${id}/toggle-acquired`;
|
||||
|
||||
// Send a PUT request to toggle the acquired status
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`API request failed with status ${response.status}`);
|
||||
}
|
||||
|
||||
// Get the updated character
|
||||
const updatedChar = await response.json();
|
||||
|
||||
// Update the character in our local data
|
||||
if (this.characters[updatedChar.name]) {
|
||||
this.characters[updatedChar.name].acquired = updatedChar.acquired;
|
||||
}
|
||||
|
||||
return updatedChar;
|
||||
} catch (error) {
|
||||
console.error('Error toggling acquired status:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a global instance of the parser
|
||||
const trustParser = new TrustParser();
|
||||
Reference in New Issue
Block a user