1
0
mirror of https://github.com/Zrips/Jobs.git synced 2024-12-11 11:51:54 +01:00
Jobs/com/gamingmesh/jobs/container/JobsPlayer.java

643 lines
16 KiB
Java
Raw Normal View History

2015-08-21 15:10:08 +02:00
/**
* Jobs Plugin for Bukkit
* Copyright (C) 2011 Zak Ford <zak.j.ford@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gamingmesh.jobs.container;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
2015-08-21 15:10:08 +02:00
import java.util.List;
import java.util.UUID;
2016-06-09 17:35:24 +02:00
import org.bukkit.Bukkit;
2015-08-21 15:10:08 +02:00
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import com.gamingmesh.jobs.Jobs;
import com.gamingmesh.jobs.dao.JobsDAO;
2015-12-10 14:13:57 +01:00
import com.gamingmesh.jobs.resources.jfep.Parser;
2015-08-21 15:10:08 +02:00
import com.gamingmesh.jobs.stuff.ChatColor;
import com.gamingmesh.jobs.stuff.Perm;
public class JobsPlayer {
2015-09-10 12:41:19 +02:00
// the player the object belongs to
private String userName;
// progression of the player in each job
2016-08-05 12:28:31 +02:00
public UUID playerUUID;
2016-03-30 15:42:36 +02:00
public ArrayList<JobProgression> progression = new ArrayList<JobProgression>();
private HashMap<String, ArrayList<BoostCounter>> boostCounter = new HashMap<String, ArrayList<BoostCounter>>();
2015-09-10 12:41:19 +02:00
// display honorific
private String honorific;
// player save status
private volatile boolean isSaved = true;
// player online status
private volatile boolean isOnline = false;
2016-06-09 17:35:24 +02:00
private OfflinePlayer OffPlayer = null;
private Player player = null;
2015-09-10 12:41:19 +02:00
private double VipSpawnerMultiplier = -1;
2015-12-10 14:13:57 +01:00
private int MoneyLimit = 0;
private int ExpLimit = 0;
2016-03-30 15:42:36 +02:00
private int PointLimit = 0;
2015-12-10 14:13:57 +01:00
2016-03-30 15:42:36 +02:00
private int userid = -1;
List<BossBarInfo> barMap = new ArrayList<BossBarInfo>();
List<String> updateBossBarFor = new ArrayList<String>();
2015-09-10 12:41:19 +02:00
// save lock
2015-11-25 16:14:48 +01:00
// public final Object saveLock = new Object();
2015-09-10 12:41:19 +02:00
// log
private List<Log> logList = new ArrayList<Log>();
2016-03-30 15:42:36 +02:00
public JobsPlayer(String userName, OfflinePlayer player) {
2015-09-10 12:41:19 +02:00
this.userName = userName;
2016-06-09 17:35:24 +02:00
this.OffPlayer = player;
2016-08-05 12:28:31 +02:00
this.player = Bukkit.getPlayer(userName);
2016-06-10 17:25:40 +02:00
}
2016-06-09 17:35:24 +02:00
public void setPlayer(Player p) {
this.player = p;
}
2016-08-05 12:28:31 +02:00
public void loadLogFromDao() {
Jobs.getJobsDAO().loadLog(this);
}
2016-04-03 16:22:44 +02:00
public synchronized List<String> getUpdateBossBarFor() {
2016-03-30 15:42:36 +02:00
return this.updateBossBarFor;
}
2016-04-03 16:22:44 +02:00
public synchronized void clearUpdateBossBarFor() {
this.updateBossBarFor.clear();
}
public synchronized List<BossBarInfo> getBossBarInfo() {
2016-03-30 15:42:36 +02:00
return this.barMap;
}
2016-04-03 16:22:44 +02:00
public synchronized void hideBossBars() {
2016-03-30 15:42:36 +02:00
for (BossBarInfo one : this.barMap) {
one.getBar().setVisible(false);
}
}
2015-09-10 12:41:19 +02:00
public List<Log> getLog() {
return this.logList;
}
2016-03-30 15:42:36 +02:00
public void setUserId(int id) {
this.userid = id;
}
public int getUserId() {
return this.userid;
}
2015-09-10 12:41:19 +02:00
/**
* Get the player
* @return the player
*/
2016-06-09 17:35:24 +02:00
public Player getPlayer() {
if (this.player != null)
return this.player;
return Bukkit.getPlayer(this.playerUUID);
2015-09-10 12:41:19 +02:00
}
/**
* Get the VipSpawnerMultiplier
* @return the Multiplier
*/
public double getVipSpawnerMultiplier() {
2016-06-09 17:35:24 +02:00
if (!this.OffPlayer.isOnline())
2015-09-10 12:41:19 +02:00
return 1.0;
if (VipSpawnerMultiplier < 0)
updateVipSpawnerMultiplier();
return this.VipSpawnerMultiplier;
}
public void updateVipSpawnerMultiplier() {
if (Perm.hasPermission(this.player, "jobs.vipspawner"))
2016-03-30 15:42:36 +02:00
this.VipSpawnerMultiplier = Jobs.getGCManager().VIPpayNearSpawnerMultiplier;
2015-09-10 12:41:19 +02:00
else
2016-03-30 15:42:36 +02:00
this.VipSpawnerMultiplier = Jobs.getGCManager().payNearSpawnerMultiplier;
2015-09-10 12:41:19 +02:00
}
/**
* Get the Boost
* @return the Boost
2015-09-10 12:41:19 +02:00
*/
public double getBoost(String JobName, BoostType type) {
return getBoost(JobName, type, false);
}
public double getBoost(String JobName, BoostType type, boolean force) {
2015-09-10 12:41:19 +02:00
if (this.player == null)
this.player = Bukkit.getPlayer(this.OffPlayer.getUniqueId());
double Boost = 1.0;
if (this.player == null)
return Boost;
long time = System.currentTimeMillis();
if (this.boostCounter.containsKey(JobName)) {
ArrayList<BoostCounter> counterList = boostCounter.get(JobName);
for (BoostCounter counter : counterList) {
if (counter.getType() != type)
continue;
if (force || time - counter.getTime() > 1000 * 60) {
Boost = getPlayerBoost(JobName, type);
counter.setBoost(Boost);
counter.setTime(time);
return Boost;
}
2016-06-25 15:27:01 +02:00
return counter.getBoost();
2016-03-30 15:42:36 +02:00
}
Boost = getPlayerBoost(JobName, type);
counterList.add(new BoostCounter(type, Boost, time));
return Boost;
2016-03-30 15:42:36 +02:00
}
Boost = getPlayerBoost(JobName, type);
ArrayList<BoostCounter> counterList = new ArrayList<BoostCounter>();
counterList.add(new BoostCounter(type, Boost, time));
boostCounter.put(JobName, counterList);
return Boost;
2016-03-30 15:42:36 +02:00
}
private Double getPlayerBoost(String JobName, BoostType type) {
double Boost = 1.0;
2016-06-26 15:12:44 +02:00
if (Perm.hasPermission(player, "jobs.boost." + JobName + "." + type.getName().toLowerCase()) ||
Perm.hasPermission(player, "jobs.boost." + JobName + ".all") ||
Perm.hasPermission(player, "jobs.boost.all.all") ||
Perm.hasPermission(player, "jobs.boost.all." + type.getName().toLowerCase())) {
Boost = Jobs.getGCManager().Boost.get(type);
2015-08-21 15:10:08 +02:00
}
return Boost;
2015-09-10 12:41:19 +02:00
}
/**
* Reloads max experience for this job.
*/
2016-03-30 15:42:36 +02:00
public void reloadMaxExperience() {
2015-09-10 12:41:19 +02:00
for (JobProgression prog : progression) {
prog.reloadMaxExperience();
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
}
2015-12-10 14:13:57 +01:00
/**
* Reloads money limit for this player.
*/
2016-03-30 15:42:36 +02:00
public void reloadMoney() {
2015-12-10 14:13:57 +01:00
int TotalLevel = 0;
for (JobProgression prog : progression) {
TotalLevel += prog.getLevel();
}
2016-03-30 15:42:36 +02:00
Parser eq = Jobs.getGCManager().maxMoneyEquation;
2015-12-10 14:13:57 +01:00
eq.setVariable("totallevel", TotalLevel);
MoneyLimit = (int) eq.getValue();
}
/**
* Reloads exp limit for this player.
*/
2016-03-30 15:42:36 +02:00
public void reloadExp() {
2015-12-10 14:13:57 +01:00
int TotalLevel = 0;
for (JobProgression prog : progression) {
TotalLevel += prog.getLevel();
}
2016-03-30 15:42:36 +02:00
Parser eq = Jobs.getGCManager().maxExpEquation;
2015-12-10 14:13:57 +01:00
eq.setVariable("totallevel", TotalLevel);
ExpLimit = (int) eq.getValue();
}
2016-04-03 16:22:44 +02:00
2016-03-30 15:42:36 +02:00
/**
* Reloads exp limit for this player.
*/
public void reloadPoint() {
int TotalLevel = 0;
for (JobProgression prog : progression) {
TotalLevel += prog.getLevel();
}
Parser eq = Jobs.getGCManager().maxPointEquation;
eq.setVariable("totallevel", TotalLevel);
PointLimit = (int) eq.getValue();
}
2016-04-03 16:22:44 +02:00
2016-03-30 15:42:36 +02:00
public void reloadLimits() {
reloadMoney();
reloadExp();
reloadPoint();
}
2016-04-03 16:22:44 +02:00
2015-12-10 14:13:57 +01:00
public int getMoneyLimit() {
return this.MoneyLimit;
}
public int getExpLimit() {
return this.ExpLimit;
}
2016-03-30 15:42:36 +02:00
public int getPointLimit() {
return this.PointLimit;
}
2015-09-10 12:41:19 +02:00
/**
* Get the list of job progressions
* @return the list of job progressions
*/
public List<JobProgression> getJobProgression() {
return Collections.unmodifiableList(progression);
}
/**
* Check if have permission
* @return true if have
*/
public boolean havePermission(String perm) {
2016-06-09 17:35:24 +02:00
if (this.player == null)
this.player = Bukkit.getPlayer(this.playerUUID);
if (this.player != null)
return Perm.hasPermission(player, perm);
2015-09-10 12:41:19 +02:00
return false;
}
/**
* Get the job progression with the certain job
* @return the job progression
*/
public JobProgression getJobProgression(Job job) {
for (JobProgression prog : progression) {
if (prog.getJob().equals(job))
return prog;
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
return null;
}
/**
* get the userName
* @return the userName
*/
public String getUserName() {
return userName;
}
/**
* get the playerUUID
* @return the playerUUID
*/
public UUID getPlayerUUID() {
return playerUUID;
}
2016-03-30 15:42:36 +02:00
public void setPlayerUUID(UUID uuid) {
playerUUID = uuid;
}
2015-09-10 12:41:19 +02:00
public String getDisplayHonorific() {
return honorific;
}
/**
* Player joins a job
* @param job - the job joined
*/
2016-08-05 12:28:31 +02:00
public boolean joinJob(Job job) {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
if (!isInJob(job)) {
int level = 1;
int exp = 0;
2016-08-05 12:28:31 +02:00
if (Jobs.getJobsDAO().checkArchive(this, job).size() > 0) {
List<Integer> info = Jobs.getJobsDAO().checkArchive(this, job);
2015-12-10 14:13:57 +01:00
level = info.get(0);
//exp = info.get(1);
2016-08-05 12:28:31 +02:00
Jobs.getJobsDAO().deleteArchive(this, job);
2015-09-10 12:41:19 +02:00
}
2015-12-10 14:13:57 +01:00
progression.add(new JobProgression(job, this, level, exp));
2015-12-10 14:13:57 +01:00
reloadMaxExperience();
2016-03-30 15:42:36 +02:00
reloadLimits();
2015-12-10 14:13:57 +01:00
reloadHonorific();
Jobs.getPermissionHandler().recalculatePermissions(this);
return true;
}
return false;
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Player leaves a job
* @param job - the job left
*/
public boolean leaveJob(Job job) {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
JobProgression prog = getJobProgression(job);
if (prog != null) {
progression.remove(prog);
reloadMaxExperience();
2016-03-30 15:42:36 +02:00
reloadLimits();
2015-12-10 14:13:57 +01:00
reloadHonorific();
Jobs.getPermissionHandler().recalculatePermissions(this);
return true;
}
return false;
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Leave all jobs
* @return on success
*/
public boolean leaveAllJobs() {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
progression.clear();
reloadHonorific();
2016-06-25 15:27:01 +02:00
Jobs.getPermissionHandler().recalculatePermissions(this);
2015-12-10 14:13:57 +01:00
return true;
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Promotes player in job
* @param job - the job being promoted
* @param levels - number of levels to promote
*/
2016-08-05 12:28:31 +02:00
public void promoteJob(Job job, int levels) {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
JobProgression prog = getJobProgression(job);
if (prog == null)
return;
if (levels <= 0)
return;
int newLevel = prog.getLevel() + levels;
2015-09-10 12:41:19 +02:00
2015-12-10 14:13:57 +01:00
int maxLevel = job.getMaxLevel();
2015-09-10 12:41:19 +02:00
2016-08-05 12:28:31 +02:00
if (this.havePermission("jobs." + job.getName() + ".vipmaxlevel") && job.getVipMaxLevel() != 0)
2015-12-10 14:13:57 +01:00
maxLevel = job.getVipMaxLevel();
2015-09-10 12:41:19 +02:00
2015-12-10 14:13:57 +01:00
if (maxLevel > 0 && newLevel > maxLevel) {
newLevel = maxLevel;
}
setLevel(job, newLevel);
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Demotes player in job
* @param job - the job being deomoted
* @param levels - number of levels to demote
*/
public void demoteJob(Job job, int levels) {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
JobProgression prog = getJobProgression(job);
if (prog == null)
return;
if (levels <= 0)
return;
int newLevel = prog.getLevel() - levels;
if (newLevel < 1) {
newLevel = 1;
}
setLevel(job, newLevel);
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Sets player to a specific level
* @param job - the job
* @param level - the level
*/
private void setLevel(Job job, int level) {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
JobProgression prog = getJobProgression(job);
if (prog == null)
return;
2015-09-10 12:41:19 +02:00
2015-12-10 14:13:57 +01:00
if (level != prog.getLevel()) {
prog.setLevel(level);
reloadHonorific();
2016-06-09 17:35:24 +02:00
Jobs.getPermissionHandler().recalculatePermissions(this);
2015-12-10 14:13:57 +01:00
}
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Player leaves a job
* @param oldjob - the old job
* @param newjob - the new job
*/
2016-08-05 12:28:31 +02:00
public boolean transferJob(Job oldjob, Job newjob) {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
2015-12-10 14:13:57 +01:00
if (!isInJob(newjob)) {
for (JobProgression prog : progression) {
if (!prog.getJob().equals(oldjob))
continue;
prog.setJob(newjob);
int maxLevel = 0;
2016-08-05 12:28:31 +02:00
if (this.havePermission("jobs." + newjob.getName() + ".vipmaxlevel"))
2015-12-10 14:13:57 +01:00
maxLevel = newjob.getVipMaxLevel();
else
maxLevel = newjob.getMaxLevel();
if (newjob.getMaxLevel() > 0 && prog.getLevel() > maxLevel) {
prog.setLevel(maxLevel);
2015-08-21 15:10:08 +02:00
}
2015-12-10 14:13:57 +01:00
reloadMaxExperience();
2016-03-30 15:42:36 +02:00
reloadLimits();
2015-12-10 14:13:57 +01:00
reloadHonorific();
Jobs.getPermissionHandler().recalculatePermissions(this);
2016-03-13 15:35:23 +01:00
2015-12-10 14:13:57 +01:00
return true;
2015-09-10 12:41:19 +02:00
}
2015-12-10 14:13:57 +01:00
}
return false;
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Checks if the player is in this job.
* @param job - the job
* @return true - they are in the job
* @return false - they are not in the job
*/
public boolean isInJob(Job job) {
for (JobProgression prog : progression) {
if (prog.getJob().equals(job))
return true;
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
return false;
}
/**
* Function that reloads your honorific
*/
public void reloadHonorific() {
StringBuilder builder = new StringBuilder();
int numJobs = progression.size();
boolean gotTitle = false;
2016-06-10 17:25:40 +02:00
if (numJobs > 0) {
2015-09-10 12:41:19 +02:00
for (JobProgression prog : progression) {
DisplayMethod method = prog.getJob().getDisplayMethod();
if (method.equals(DisplayMethod.NONE))
continue;
if (gotTitle) {
2016-03-30 15:42:36 +02:00
builder.append(Jobs.getGCManager().getModifyChatSeparator());
2015-09-10 12:41:19 +02:00
gotTitle = false;
2015-08-21 15:10:08 +02:00
}
2016-06-25 15:27:01 +02:00
Title title = Jobs.gettitleManager().getTitleForLevel(prog.getLevel());
2015-09-10 12:41:19 +02:00
if (numJobs == 1) {
if (method.equals(DisplayMethod.FULL) || method.equals(DisplayMethod.TITLE)) {
if (title != null) {
String honorificpart = title.getChatColor() + title.getName() + ChatColor.WHITE;
if (honorificpart.contains("{level}"))
honorificpart = honorificpart.replace("{level}", String.valueOf(prog.getLevel()));
builder.append(honorificpart);
gotTitle = true;
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
}
if (method.equals(DisplayMethod.FULL) || method.equals(DisplayMethod.JOB)) {
if (gotTitle) {
builder.append(" ");
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
String honorificpart = prog.getJob().getChatColor() + prog.getJob().getName() + ChatColor.WHITE;
if (honorificpart.contains("{level}"))
honorificpart = honorificpart.replace("{level}", String.valueOf(prog.getLevel()));
builder.append(honorificpart);
gotTitle = true;
}
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
if (numJobs > 1 && (method.equals(DisplayMethod.FULL) || method.equals(DisplayMethod.TITLE)) || method.equals(DisplayMethod.SHORT_FULL) || method.equals(
DisplayMethod.SHORT_TITLE)) {
// add title to honorific
if (title != null) {
String honorificpart = title.getChatColor() + title.getShortName() + ChatColor.WHITE;
if (honorificpart.contains("{level}"))
honorificpart = honorificpart.replace("{level}", String.valueOf(prog.getLevel()));
builder.append(honorificpart);
gotTitle = true;
}
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
if (numJobs > 1 && (method.equals(DisplayMethod.FULL) || method.equals(DisplayMethod.JOB)) || method.equals(DisplayMethod.SHORT_FULL) || method.equals(
DisplayMethod.SHORT_JOB)) {
String honorificpart = prog.getJob().getChatColor() + prog.getJob().getShortName() + ChatColor.WHITE;
if (honorificpart.contains("{level}"))
honorificpart = honorificpart.replace("{level}", String.valueOf(prog.getLevel()));
builder.append(honorificpart);
gotTitle = true;
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
}
2016-06-10 17:25:40 +02:00
} else {
2015-09-10 12:41:19 +02:00
Job nonejob = Jobs.getNoneJob();
if (nonejob != null) {
DisplayMethod metod = nonejob.getDisplayMethod();
if (metod.equals(DisplayMethod.FULL) || metod.equals(DisplayMethod.TITLE)) {
String honorificpart = Jobs.getNoneJob().getChatColor() + Jobs.getNoneJob().getName() + ChatColor.WHITE;
if (honorificpart.contains("{level}"))
honorificpart = honorificpart.replace("{level}", "");
builder.append(honorificpart);
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
if (metod.equals(DisplayMethod.SHORT_FULL) || metod.equals(DisplayMethod.SHORT_TITLE) || metod.equals(DisplayMethod.SHORT_JOB)) {
String honorificpart = Jobs.getNoneJob().getChatColor() + Jobs.getNoneJob().getShortName() + ChatColor.WHITE;
if (honorificpart.contains("{level}"))
honorificpart = honorificpart.replace("{level}", "");
builder.append(honorificpart);
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
}
2015-08-21 15:10:08 +02:00
}
2015-09-10 12:41:19 +02:00
honorific = builder.toString().trim();
2016-03-13 15:35:23 +01:00
if (honorific.length() > 0)
2016-03-30 15:42:36 +02:00
honorific = Jobs.getGCManager().getModifyChatPrefix() + honorific + Jobs.getGCManager().getModifyChatSuffix();
2016-01-11 16:48:56 +01:00
2015-09-10 12:41:19 +02:00
}
/**
* Performs player save
* @param dao
*/
2016-08-05 12:28:31 +02:00
public void save() {
2015-11-25 16:14:48 +01:00
// synchronized (saveLock) {
if (!isSaved()) {
2016-08-05 12:28:31 +02:00
JobsDAO dao = Jobs.getJobsDAO();
2015-11-25 16:14:48 +01:00
dao.save(this);
dao.saveLog(this);
2016-03-30 15:42:36 +02:00
dao.savePoints(this);
2015-11-25 16:14:48 +01:00
setSaved(true);
2015-08-21 15:10:08 +02:00
}
2015-11-25 16:14:48 +01:00
// }
2015-09-10 12:41:19 +02:00
}
/**
* Perform connect
*/
public void onConnect() {
isOnline = true;
}
/**
* Perform disconnect
*
*/
public void onDisconnect() {
2016-03-30 15:42:36 +02:00
// Jobs.getJobsDAO().savePoints(this);
clearBossMaps();
2015-09-10 12:41:19 +02:00
isOnline = false;
}
2016-03-30 15:42:36 +02:00
public void clearBossMaps() {
for (BossBarInfo one : barMap) {
one.cancel();
}
barMap.clear();
}
2015-09-10 12:41:19 +02:00
/**
* Whether or not player is online
* @return true if online, otherwise false
*/
public boolean isOnline() {
return isOnline;
}
public boolean isSaved() {
return isSaved;
}
public void setSaved(boolean value) {
isSaved = value;
}
2015-08-21 15:10:08 +02:00
}