2013-02-05 18:56:31 +01:00
package com.gmail.nossr50.database ;
2012-04-27 11:47:11 +02:00
import java.io.BufferedReader ;
import java.io.FileReader ;
2013-02-05 21:29:57 +01:00
import java.io.FileWriter ;
import java.io.IOException ;
2012-04-27 11:47:11 +02:00
import java.util.ArrayList ;
2013-01-01 04:40:33 +01:00
import java.util.Collections ;
import java.util.Comparator ;
2013-01-15 23:49:20 +01:00
import java.util.HashMap ;
2013-01-01 04:40:33 +01:00
import java.util.List ;
2013-04-18 23:37:36 +02:00
import java.util.Map ;
2012-04-27 11:47:11 +02:00
2012-06-07 00:02:22 +02:00
import com.gmail.nossr50.mcMMO ;
2013-02-05 21:29:57 +01:00
import com.gmail.nossr50.config.Config ;
2013-03-01 06:52:01 +01:00
import com.gmail.nossr50.datatypes.database.PlayerStat ;
import com.gmail.nossr50.datatypes.skills.SkillType ;
2013-02-13 17:45:48 +01:00
import com.gmail.nossr50.util.StringUtils ;
2012-04-27 11:47:11 +02:00
2013-04-18 23:37:36 +02:00
public final class FlatfileDatabaseManager {
2013-01-15 23:49:20 +01:00
private static HashMap < SkillType , List < PlayerStat > > playerStatHash = new HashMap < SkillType , List < PlayerStat > > ( ) ;
2013-02-04 16:33:34 +01:00
private static List < PlayerStat > powerLevels = new ArrayList < PlayerStat > ( ) ;
2013-01-16 21:02:41 +01:00
private static long lastUpdate = 0 ;
2013-01-21 23:22:54 +01:00
2013-03-01 06:52:01 +01:00
private static final long UPDATE_WAIT_TIME = 600000L ; // 10 minutes
private static final long ONE_MONTH = 2630000000L ;
2013-04-18 23:37:36 +02:00
private FlatfileDatabaseManager ( ) { }
2013-01-26 23:01:55 +01:00
2012-04-27 11:47:11 +02:00
/ * *
2013-01-15 23:49:20 +01:00
* Update the leader boards .
2012-04-27 11:47:11 +02:00
* /
2013-01-15 23:49:20 +01:00
public static void updateLeaderboards ( ) {
2013-03-01 06:52:01 +01:00
// Only update FFS leaderboards every 10 minutes.. this puts a lot of strain on the server (depending on the size of the database) and should not be done frequently
if ( System . currentTimeMillis ( ) < lastUpdate + UPDATE_WAIT_TIME ) {
return ;
2013-01-21 23:15:53 +01:00
}
2013-01-21 23:22:54 +01:00
2013-04-18 23:37:36 +02:00
String usersFilePath = mcMMO . getUsersFilePath ( ) ;
2013-03-01 06:52:01 +01:00
lastUpdate = System . currentTimeMillis ( ) ; // Log when the last update was run
2013-03-01 21:55:10 +01:00
powerLevels . clear ( ) ; // Clear old values from the power levels
2013-03-01 06:52:01 +01:00
// Initialize lists
List < PlayerStat > mining = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > woodcutting = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > herbalism = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > excavation = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > acrobatics = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > repair = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > swords = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > axes = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > archery = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > unarmed = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > taming = new ArrayList < PlayerStat > ( ) ;
List < PlayerStat > fishing = new ArrayList < PlayerStat > ( ) ;
// Read from the FlatFile database and fill our arrays with information
2012-04-27 11:47:11 +02:00
try {
2013-04-18 23:37:36 +02:00
BufferedReader in = new BufferedReader ( new FileReader ( usersFilePath ) ) ;
2012-04-27 11:47:11 +02:00
String line = " " ;
ArrayList < String > players = new ArrayList < String > ( ) ;
while ( ( line = in . readLine ( ) ) ! = null ) {
2013-03-14 15:25:54 +01:00
String [ ] data = line . split ( " : " ) ;
2013-01-14 22:09:11 +01:00
2013-03-14 15:25:54 +01:00
String playerName = data [ 0 ] ;
2012-04-27 11:47:11 +02:00
int powerLevel = 0 ;
2013-03-01 06:52:01 +01:00
// Prevent the same player from being added multiple times (I'd like to note that this shouldn't happen...)
2013-03-14 15:25:54 +01:00
if ( players . contains ( playerName ) ) {
2012-04-27 11:47:11 +02:00
continue ;
}
2013-01-10 04:43:21 +01:00
2013-03-14 15:25:54 +01:00
players . add ( playerName ) ;
2012-04-27 11:47:11 +02:00
2013-04-18 23:37:36 +02:00
powerLevel + = loadStat ( mining , playerName , data , 1 ) ;
powerLevel + = loadStat ( woodcutting , playerName , data , 5 ) ;
powerLevel + = loadStat ( repair , playerName , data , 7 ) ;
powerLevel + = loadStat ( unarmed , playerName , data , 8 ) ;
powerLevel + = loadStat ( herbalism , playerName , data , 9 ) ;
powerLevel + = loadStat ( excavation , playerName , data , 10 ) ;
powerLevel + = loadStat ( archery , playerName , data , 11 ) ;
powerLevel + = loadStat ( swords , playerName , data , 12 ) ;
powerLevel + = loadStat ( axes , playerName , data , 13 ) ;
powerLevel + = loadStat ( acrobatics , playerName , data , 14 ) ;
powerLevel + = loadStat ( taming , playerName , data , 24 ) ;
powerLevel + = loadStat ( fishing , playerName , data , 34 ) ;
2012-04-27 11:47:11 +02:00
2013-03-14 15:25:54 +01:00
powerLevels . add ( new PlayerStat ( playerName , powerLevel ) ) ;
2012-04-27 11:47:11 +02:00
}
in . close ( ) ;
}
catch ( Exception e ) {
2013-04-18 23:37:36 +02:00
mcMMO . p . getLogger ( ) . severe ( " Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?) " + e . toString ( ) ) ;
2012-04-27 11:47:11 +02:00
}
2013-01-01 04:40:33 +01:00
SkillComparator c = new SkillComparator ( ) ;
2013-03-01 06:52:01 +01:00
2013-01-15 23:49:20 +01:00
Collections . sort ( mining , c ) ;
Collections . sort ( woodcutting , c ) ;
Collections . sort ( repair , c ) ;
Collections . sort ( unarmed , c ) ;
Collections . sort ( herbalism , c ) ;
Collections . sort ( excavation , c ) ;
Collections . sort ( archery , c ) ;
Collections . sort ( swords , c ) ;
Collections . sort ( axes , c ) ;
Collections . sort ( acrobatics , c ) ;
Collections . sort ( taming , c ) ;
Collections . sort ( fishing , c ) ;
2013-02-04 16:33:34 +01:00
Collections . sort ( powerLevels , c ) ;
2013-01-21 23:22:54 +01:00
2013-01-15 23:49:20 +01:00
playerStatHash . put ( SkillType . MINING , mining ) ;
playerStatHash . put ( SkillType . WOODCUTTING , woodcutting ) ;
playerStatHash . put ( SkillType . REPAIR , repair ) ;
playerStatHash . put ( SkillType . UNARMED , unarmed ) ;
playerStatHash . put ( SkillType . HERBALISM , herbalism ) ;
playerStatHash . put ( SkillType . EXCAVATION , excavation ) ;
playerStatHash . put ( SkillType . ARCHERY , archery ) ;
playerStatHash . put ( SkillType . SWORDS , swords ) ;
playerStatHash . put ( SkillType . AXES , axes ) ;
playerStatHash . put ( SkillType . ACROBATICS , acrobatics ) ;
playerStatHash . put ( SkillType . TAMING , taming ) ;
playerStatHash . put ( SkillType . FISHING , fishing ) ;
2012-04-27 11:47:11 +02:00
}
/ * *
* Retrieve leaderboard info .
*
2013-01-31 01:42:40 +01:00
* @param skillType Skill to retrieve info on .
* @param pageNumber Which page in the leaderboards to retrieve
2012-04-27 11:47:11 +02:00
* @return the requested leaderboard information
* /
2013-02-04 16:33:34 +01:00
public static String [ ] retrieveInfo ( String skillType , int pageNumber ) {
2013-01-21 23:15:53 +01:00
String [ ] info = new String [ 10 ] ;
2013-02-04 16:33:34 +01:00
List < PlayerStat > statsList ;
2013-01-15 23:49:20 +01:00
2013-02-04 16:33:34 +01:00
if ( skillType . equalsIgnoreCase ( " all " ) ) {
statsList = powerLevels ;
}
else {
statsList = playerStatHash . get ( SkillType . getSkill ( skillType ) ) ;
}
2013-03-22 17:38:52 +01:00
if ( pageNumber < 1 ) {
pageNumber = 1 ;
}
2013-03-14 15:25:54 +01:00
int destination = ( pageNumber - 1 ) * 10 ;
2013-02-04 16:33:34 +01:00
2013-03-14 15:25:54 +01:00
for ( int i = 0 ; i < 10 ; i + + ) {
2013-03-22 17:38:52 +01:00
if ( destination + i < statsList . size ( ) ) {
PlayerStat ps = statsList . get ( destination + i ) ;
info [ i ] = ps . name + " : " + ps . statVal ;
}
2013-02-04 16:33:34 +01:00
}
2013-01-21 23:22:54 +01:00
2013-02-04 16:33:34 +01:00
return info ;
}
2013-02-05 21:29:57 +01:00
public static boolean removeFlatFileUser ( String playerName ) {
boolean worked = false ;
BufferedReader in = null ;
FileWriter out = null ;
String usersFilePath = mcMMO . getUsersFilePath ( ) ;
try {
FileReader file = new FileReader ( usersFilePath ) ;
in = new BufferedReader ( file ) ;
StringBuilder writer = new StringBuilder ( ) ;
String line = " " ;
while ( ( line = in . readLine ( ) ) ! = null ) {
2013-03-01 06:52:01 +01:00
// Write out the same file but when we get to the player we want to remove, we skip his line.
2013-02-05 21:29:57 +01:00
if ( ! line . split ( " : " ) [ 0 ] . equalsIgnoreCase ( playerName ) ) {
writer . append ( line ) . append ( " \ r \ n " ) ;
}
else {
2013-02-13 04:18:47 +01:00
mcMMO . p . getLogger ( ) . info ( " User found, removing... " ) ;
2013-02-05 21:29:57 +01:00
worked = true ;
2013-03-01 06:52:01 +01:00
continue ; // Skip the player
2013-02-05 21:29:57 +01:00
}
}
2013-03-01 06:52:01 +01:00
out = new FileWriter ( usersFilePath ) ; // Write out the new file
2013-02-05 21:29:57 +01:00
out . write ( writer . toString ( ) ) ;
}
catch ( Exception e ) {
mcMMO . p . getLogger ( ) . severe ( " Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?) " + e . toString ( ) ) ;
}
finally {
if ( in ! = null ) {
try {
in . close ( ) ;
}
catch ( IOException ex ) {
ex . printStackTrace ( ) ;
}
}
if ( out ! = null ) {
try {
out . close ( ) ;
}
catch ( IOException ex ) {
ex . printStackTrace ( ) ;
}
}
}
return worked ;
}
2013-04-18 23:37:36 +02:00
public static int purgePowerlessFlatfile ( ) {
2013-02-05 21:29:57 +01:00
mcMMO . p . getLogger ( ) . info ( " Purging powerless users... " ) ;
int purgedUsers = 0 ;
2013-03-14 15:25:54 +01:00
2013-02-05 23:09:20 +01:00
for ( PlayerStat stat : powerLevels ) {
2013-03-14 15:25:54 +01:00
if ( stat . statVal = = 0 & & ! mcMMO . p . getServer ( ) . getOfflinePlayer ( stat . name ) . isOnline ( ) & & removeFlatFileUser ( stat . name ) ) {
2013-02-05 21:29:57 +01:00
purgedUsers + + ;
}
}
2013-04-18 23:37:36 +02:00
return purgedUsers ;
2013-02-05 21:29:57 +01:00
}
2013-04-18 23:37:36 +02:00
public static int removeOldFlatfileUsers ( ) {
2013-02-05 21:29:57 +01:00
int removedPlayers = 0 ;
long currentTime = System . currentTimeMillis ( ) ;
2013-03-01 06:52:01 +01:00
long purgeTime = ONE_MONTH * Config . getInstance ( ) . getOldUsersCutoff ( ) ;
2013-02-05 21:29:57 +01:00
BufferedReader in = null ;
FileWriter out = null ;
String usersFilePath = mcMMO . getUsersFilePath ( ) ;
try {
FileReader file = new FileReader ( usersFilePath ) ;
in = new BufferedReader ( file ) ;
StringBuilder writer = new StringBuilder ( ) ;
String line = " " ;
while ( ( line = in . readLine ( ) ) ! = null ) {
2013-03-01 06:52:01 +01:00
// Write out the same file but when we get to the player we want to remove, we skip his line.
2013-02-05 23:09:20 +01:00
String [ ] splitLine = line . split ( " : " ) ;
2013-02-05 23:19:53 +01:00
if ( splitLine . length > 37 ) {
2013-02-13 17:45:48 +01:00
if ( currentTime - ( StringUtils . getLong ( line . split ( " : " ) [ 37 ] ) * 1000 ) < = purgeTime ) {
2013-02-05 23:19:53 +01:00
writer . append ( line ) . append ( " \ r \ n " ) ;
}
else {
2013-02-13 04:18:47 +01:00
mcMMO . p . getLogger ( ) . info ( " User found, removing... " ) ;
2013-02-05 23:19:53 +01:00
removedPlayers + + ;
2013-03-01 06:52:01 +01:00
continue ; // Skip the player
2013-02-05 23:19:53 +01:00
}
2013-02-05 21:29:57 +01:00
}
else {
2013-02-05 23:19:53 +01:00
writer . append ( line ) . append ( " \ r \ n " ) ;
2013-02-05 21:29:57 +01:00
}
}
2013-03-01 06:52:01 +01:00
out = new FileWriter ( usersFilePath ) ; // Write out the new file
2013-02-05 21:29:57 +01:00
out . write ( writer . toString ( ) ) ;
}
catch ( Exception e ) {
mcMMO . p . getLogger ( ) . severe ( " Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?) " + e . toString ( ) ) ;
}
finally {
if ( in ! = null ) {
try {
in . close ( ) ;
}
catch ( IOException ex ) {
ex . printStackTrace ( ) ;
}
}
if ( out ! = null ) {
try {
out . close ( ) ;
}
catch ( IOException ex ) {
ex . printStackTrace ( ) ;
}
}
}
return removedPlayers ;
}
2013-04-18 23:37:36 +02:00
private static Integer getPlayerRank ( String playerName , List < PlayerStat > statsList ) {
2013-03-14 15:25:54 +01:00
int currentPos = 1 ;
if ( statsList = = null ) {
2013-04-18 23:37:36 +02:00
return null ;
2013-03-14 15:25:54 +01:00
}
for ( PlayerStat stat : statsList ) {
if ( stat . name . equalsIgnoreCase ( playerName ) ) {
2013-04-18 23:37:36 +02:00
return currentPos ;
2013-03-14 15:25:54 +01:00
}
currentPos + + ;
}
2013-04-18 23:37:36 +02:00
return null ;
}
public static Map < String , Integer > getPlayerRanks ( String playerName ) {
updateLeaderboards ( ) ;
Map < String , Integer > skills = new HashMap < String , Integer > ( ) ;
for ( SkillType skill : SkillType . values ( ) ) {
2013-04-26 16:51:17 +02:00
if ( skill . isChildSkill ( ) ) {
continue ;
}
skills . put ( skill . name ( ) , getPlayerRank ( playerName , playerStatHash . get ( skill ) ) ) ;
2013-04-18 23:37:36 +02:00
}
skills . put ( " ALL " , getPlayerRank ( playerName , powerLevels ) ) ;
return skills ;
}
private static int loadStat ( List < PlayerStat > statList , String playerName , String [ ] data , int dataIndex ) {
if ( data . length > dataIndex ) {
int statValue = Integer . parseInt ( data [ dataIndex ] ) ;
statList . add ( new PlayerStat ( playerName , statValue ) ) ;
return statValue ;
}
return 0 ;
2013-03-14 15:25:54 +01:00
}
2013-03-01 06:52:01 +01:00
private static class SkillComparator implements Comparator < PlayerStat > {
@Override
public int compare ( PlayerStat o1 , PlayerStat o2 ) {
return ( o2 . statVal - o1 . statVal ) ;
}
}
2012-04-27 11:47:11 +02:00
}