Non-bogus ProfileMatcher.
This commit is contained in:
@@ -5,7 +5,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class PlayerProfile {
|
public class PlayerProfile {
|
||||||
//From Bartle/Yee models of player psychology: achiever, killer, explorer, manipulator
|
//From Bartle/Yee models of player psychology: achiever, killer, explorer, manipulator
|
||||||
public enum TYPE { RUNNER, SHOOTER, JUMPER, BUMPER}
|
public enum TYPE { BUMPER, COLLECTOR, RUNNER, SHOOTER, JUMPER}
|
||||||
//Dreyfus model of skill acquisition:
|
//Dreyfus model of skill acquisition:
|
||||||
public enum SKILL_LEVEL { NOVICE, BEGINNER, COMPETENT, PROFICIENT, EXPERT}
|
public enum SKILL_LEVEL { NOVICE, BEGINNER, COMPETENT, PROFICIENT, EXPERT}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,172 @@
|
|||||||
package dk.itu.mario.level.matcher;
|
package dk.itu.mario.level.matcher;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import dk.itu.mario.MarioInterface.GamePlay;
|
import dk.itu.mario.MarioInterface.GamePlay;
|
||||||
import dk.itu.mario.engine.DataRecorder;
|
import dk.itu.mario.engine.DataRecorder;
|
||||||
import dk.itu.mario.level.PlayerProfile;
|
import dk.itu.mario.level.PlayerProfile;
|
||||||
import dk.itu.mario.level.PlayerProfile.SKILL_LEVEL;
|
import dk.itu.mario.level.PlayerProfile.SKILL_LEVEL;
|
||||||
import dk.itu.mario.level.PlayerProfile.TYPE;
|
|
||||||
|
|
||||||
public class ProfileMatcher {
|
public class ProfileMatcher {
|
||||||
|
public enum SKILL { BUMP, COLLECT, JUMP, RUN, SHOOT, STOMP }
|
||||||
|
|
||||||
|
private static Map<PlayerProfile.TYPE, Map<SKILL,Integer>> referenceMetrics = new HashMap<PlayerProfile.TYPE, Map<SKILL,Integer>>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<SKILL,Integer> canonicalVector = new HashMap<SKILL,Integer>();
|
||||||
|
canonicalVector.put(SKILL.BUMP, 100);
|
||||||
|
canonicalVector.put(SKILL.COLLECT, 50);
|
||||||
|
canonicalVector.put(SKILL.JUMP, 50);
|
||||||
|
canonicalVector.put(SKILL.RUN, 0);
|
||||||
|
canonicalVector.put(SKILL.SHOOT, 0);
|
||||||
|
canonicalVector.put(SKILL.STOMP, 0);
|
||||||
|
referenceMetrics.put(PlayerProfile.TYPE.BUMPER, canonicalVector);
|
||||||
|
|
||||||
|
canonicalVector = new HashMap<SKILL,Integer>();
|
||||||
|
canonicalVector.put(SKILL.BUMP, 50);
|
||||||
|
canonicalVector.put(SKILL.COLLECT, 100);
|
||||||
|
canonicalVector.put(SKILL.JUMP, 50);
|
||||||
|
canonicalVector.put(SKILL.RUN, 0);
|
||||||
|
canonicalVector.put(SKILL.SHOOT, 0);
|
||||||
|
canonicalVector.put(SKILL.STOMP, 0);
|
||||||
|
referenceMetrics.put(PlayerProfile.TYPE.COLLECTOR, canonicalVector);
|
||||||
|
|
||||||
|
canonicalVector = new HashMap<SKILL,Integer>();
|
||||||
|
canonicalVector.put(SKILL.BUMP, 50);
|
||||||
|
canonicalVector.put(SKILL.COLLECT, 0);
|
||||||
|
canonicalVector.put(SKILL.JUMP, 100);
|
||||||
|
canonicalVector.put(SKILL.RUN, 25);
|
||||||
|
canonicalVector.put(SKILL.SHOOT, 0);
|
||||||
|
canonicalVector.put(SKILL.STOMP, 0);
|
||||||
|
referenceMetrics.put(PlayerProfile.TYPE.JUMPER, canonicalVector);
|
||||||
|
|
||||||
|
canonicalVector = new HashMap<SKILL,Integer>();
|
||||||
|
canonicalVector.put(SKILL.BUMP, 0);
|
||||||
|
canonicalVector.put(SKILL.COLLECT, 0);
|
||||||
|
canonicalVector.put(SKILL.JUMP, 25);
|
||||||
|
canonicalVector.put(SKILL.RUN, 100);
|
||||||
|
canonicalVector.put(SKILL.SHOOT, 25);
|
||||||
|
canonicalVector.put(SKILL.STOMP, 0);
|
||||||
|
referenceMetrics.put(PlayerProfile.TYPE.RUNNER, canonicalVector);
|
||||||
|
|
||||||
|
canonicalVector = new HashMap<SKILL,Integer>();
|
||||||
|
canonicalVector.put(SKILL.BUMP, 0);
|
||||||
|
canonicalVector.put(SKILL.COLLECT, 0);
|
||||||
|
canonicalVector.put(SKILL.JUMP, 25);
|
||||||
|
canonicalVector.put(SKILL.RUN, 50);
|
||||||
|
canonicalVector.put(SKILL.SHOOT, 100);
|
||||||
|
canonicalVector.put(SKILL.STOMP, 0);
|
||||||
|
referenceMetrics.put(PlayerProfile.TYPE.SHOOTER, canonicalVector);
|
||||||
|
}
|
||||||
|
|
||||||
public static PlayerProfile getMatchingProfile(GamePlay playerMetrics, DataRecorder detailedInfo) {
|
public static PlayerProfile getMatchingProfile(GamePlay playerMetrics, DataRecorder detailedInfo) {
|
||||||
System.out.println("Selecting PlayerProfile based on GamePlay metrics, DataRecorder logs.");
|
System.out.println("Selecting PlayerProfile based on GamePlay metrics, DataRecorder logs.");
|
||||||
return new PlayerProfile(SKILL_LEVEL.BEGINNER, TYPE.JUMPER);
|
|
||||||
|
int bumperScore = 0;
|
||||||
|
int collectorScore = 0;
|
||||||
|
int jumperScore = 0;
|
||||||
|
int runnerScore = 0;
|
||||||
|
int shooterScore = 0;
|
||||||
|
int stomperScore = 0;
|
||||||
|
|
||||||
|
bumperScore += playerMetrics.percentageBlocksDestroyed * 20;
|
||||||
|
bumperScore += playerMetrics.percentageCoinBlocksDestroyed * 20;
|
||||||
|
bumperScore += playerMetrics.percentageEmptyBlockesDestroyed * 20;
|
||||||
|
bumperScore += playerMetrics.percentagePowerBlockDestroyed * 20;
|
||||||
|
bumperScore += 4 * Math.min(5, playerMetrics.kickedShells);
|
||||||
|
|
||||||
|
collectorScore += playerMetrics.coinsCollected / 35.0;
|
||||||
|
|
||||||
|
jumperScore = Math.min(100, playerMetrics.jumpsNumber);
|
||||||
|
|
||||||
|
runnerScore = playerMetrics.timeRunningRight / playerMetrics.totalTime;
|
||||||
|
|
||||||
|
shooterScore += 10 * Math.min(10, playerMetrics.enemyKillByFire / 10.0);
|
||||||
|
|
||||||
|
stomperScore += Math.min(100, 2 * (playerMetrics.GoombasKilled + playerMetrics.GreenTurtlesKilled + playerMetrics.RedTurtlesKilled));
|
||||||
|
|
||||||
|
clampToPercentRange(bumperScore);
|
||||||
|
clampToPercentRange(collectorScore);
|
||||||
|
clampToPercentRange(jumperScore);
|
||||||
|
clampToPercentRange(runnerScore);
|
||||||
|
clampToPercentRange(shooterScore);
|
||||||
|
clampToPercentRange(stomperScore);
|
||||||
|
|
||||||
|
System.out.println("bumperScore: " + bumperScore);
|
||||||
|
System.out.println("collectorScore: " + collectorScore);
|
||||||
|
System.out.println("jumperScore: " + jumperScore);
|
||||||
|
System.out.println("shooterScore: " + shooterScore);
|
||||||
|
System.out.println("stomperScore: " + stomperScore);
|
||||||
|
|
||||||
|
Map<SKILL,Integer> playerProfileVector = new HashMap<SKILL,Integer>();
|
||||||
|
playerProfileVector.put(SKILL.BUMP, bumperScore);
|
||||||
|
playerProfileVector.put(SKILL.COLLECT, collectorScore);
|
||||||
|
playerProfileVector.put(SKILL.JUMP, jumperScore);
|
||||||
|
playerProfileVector.put(SKILL.RUN, runnerScore);
|
||||||
|
playerProfileVector.put(SKILL.SHOOT, shooterScore);
|
||||||
|
playerProfileVector.put(SKILL.STOMP, stomperScore);
|
||||||
|
|
||||||
|
double minDist = Double.MAX_VALUE;
|
||||||
|
PlayerProfile.TYPE closestMatch = PlayerProfile.TYPE.RUNNER;
|
||||||
|
|
||||||
|
for (PlayerProfile.TYPE type : PlayerProfile.TYPE.values()) {
|
||||||
|
Map<SKILL,Integer> canonicalVector = ProfileMatcher.referenceMetrics.get(type);
|
||||||
|
double distance = 0.0;
|
||||||
|
for (SKILL skill : SKILL.values()) {
|
||||||
|
distance += Math.pow(canonicalVector.get(skill) - playerProfileVector.get(skill), 2);
|
||||||
|
}
|
||||||
|
if (distance < minDist) {
|
||||||
|
minDist = distance;
|
||||||
|
closestMatch = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL_LEVEL skillLevel;
|
||||||
|
|
||||||
|
int keyScore = getKeyScore(playerProfileVector, closestMatch);
|
||||||
|
|
||||||
|
if (keyScore <= 20) {
|
||||||
|
skillLevel = SKILL_LEVEL.NOVICE;
|
||||||
|
} else if (keyScore <= 40) {
|
||||||
|
skillLevel = SKILL_LEVEL.BEGINNER;
|
||||||
|
} else if (keyScore <= 60) {
|
||||||
|
skillLevel = SKILL_LEVEL.COMPETENT;
|
||||||
|
} else if (keyScore <= 80) {
|
||||||
|
skillLevel = SKILL_LEVEL.PROFICIENT;
|
||||||
|
} else {
|
||||||
|
skillLevel = SKILL_LEVEL.EXPERT;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Skill level for this " + closestMatch + " is " + skillLevel + " (based on a score of " + keyScore + " out of 100.)");
|
||||||
|
|
||||||
|
return new PlayerProfile(skillLevel, closestMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getKeyScore(Map<SKILL, Integer> playerProfileVector, PlayerProfile.TYPE playerProfileType) {
|
||||||
|
switch (playerProfileType) {
|
||||||
|
case BUMPER :
|
||||||
|
return playerProfileVector.get(SKILL.BUMP);
|
||||||
|
case COLLECTOR :
|
||||||
|
return playerProfileVector.get(SKILL.COLLECT);
|
||||||
|
case JUMPER :
|
||||||
|
return playerProfileVector.get(SKILL.JUMP);
|
||||||
|
case RUNNER :
|
||||||
|
return playerProfileVector.get(SKILL.RUN);
|
||||||
|
case SHOOTER :
|
||||||
|
return playerProfileVector.get(SKILL.SHOOT);
|
||||||
|
default :
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clampToPercentRange(int value) {
|
||||||
|
if (value < 0) {
|
||||||
|
return 0;
|
||||||
|
} else if (value > 100) {
|
||||||
|
return 100;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user