Playtesting tab
Adding a new playtesting tab that explains the PC playtesting initiative. A new 't' flag is now part of the user type as a result. The three PC Playtesting formats will not show unless the user opts in.
This commit is contained in:
@@ -83,8 +83,13 @@ public class GempukkuHttpRequestHandler extends SimpleChannelInboundHandler<Full
|
||||
if (uri.indexOf("?") > -1)
|
||||
uri = uri.substring(0, uri.indexOf("?"));
|
||||
|
||||
String ip = httpRequest.headers().get("X-Forwarded-For");
|
||||
|
||||
if(ip == null)
|
||||
ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
|
||||
|
||||
final RequestInformation requestInformation = new RequestInformation(httpRequest.getUri(),
|
||||
httpRequest.headers().get("X-Forwarded-For"),
|
||||
ip,
|
||||
System.currentTimeMillis());
|
||||
|
||||
ResponseSender responseSender = new ResponseSender(ctx, httpRequest);
|
||||
|
||||
@@ -286,11 +286,17 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
|
||||
|
||||
Document doc = documentBuilder.newDocument();
|
||||
|
||||
Player player = getResourceOwnerSafely(request, null);
|
||||
|
||||
Element hall = doc.createElement("hall");
|
||||
hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(resourceOwner, CollectionType.MY_CARDS.getCode()).getCurrency()));
|
||||
|
||||
_hallServer.signupUserForHall(resourceOwner, new SerializeHallInfoVisitor(doc, hall));
|
||||
for (Map.Entry<String, LotroFormat> format : _formatLibrary.getHallFormats().entrySet()) {
|
||||
//playtest formats are opt-in
|
||||
if (format.getKey().startsWith("test") && !player.getType().contains("t"))
|
||||
continue;
|
||||
|
||||
Element formatElem = doc.createElement("format");
|
||||
formatElem.setAttribute("type", format.getKey());
|
||||
formatElem.appendChild(doc.createTextNode(format.getValue().getName()));
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.gempukku.lotro.async.handler;
|
||||
|
||||
import com.gempukku.lotro.DateUtils;
|
||||
import com.gempukku.lotro.async.HttpProcessingException;
|
||||
import com.gempukku.lotro.async.ResponseWriter;
|
||||
import com.gempukku.lotro.cache.CacheManager;
|
||||
import com.gempukku.lotro.collection.CollectionsManager;
|
||||
import com.gempukku.lotro.common.ApplicationConfiguration;
|
||||
import com.gempukku.lotro.db.LeagueDAO;
|
||||
import com.gempukku.lotro.db.PlayerDAO;
|
||||
import com.gempukku.lotro.db.vo.CollectionType;
|
||||
import com.gempukku.lotro.draft2.SoloDraftDefinitions;
|
||||
import com.gempukku.lotro.game.CardCollection;
|
||||
import com.gempukku.lotro.game.CardSets;
|
||||
import com.gempukku.lotro.game.LotroCardBlueprintLibrary;
|
||||
import com.gempukku.lotro.game.Player;
|
||||
import com.gempukku.lotro.game.formats.LotroFormatLibrary;
|
||||
import com.gempukku.lotro.hall.HallServer;
|
||||
import com.gempukku.lotro.league.*;
|
||||
import com.gempukku.lotro.service.AdminService;
|
||||
import com.gempukku.lotro.tournament.TournamentService;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class PlaytestRequestHandler extends LotroServerRequestHandler implements UriRequestHandler {
|
||||
|
||||
private PlayerDAO _playerDAO;
|
||||
|
||||
public PlaytestRequestHandler(Map<Type, Object> context) {
|
||||
super(context);
|
||||
_playerDAO = extractObject(context, PlayerDAO.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(String uri, HttpRequest request, Map<Type, Object> context, ResponseWriter responseWriter, String remoteIp) throws Exception {
|
||||
if (uri.equals("/addTesterFlag") && request.getMethod() == HttpMethod.POST) {
|
||||
addTesterFlag(request, responseWriter);
|
||||
} else if (uri.equals("/removeTesterFlag") && request.getMethod() == HttpMethod.POST) {
|
||||
removeTesterFlag(request, responseWriter);
|
||||
} else if (uri.equals("/getTesterFlag") && request.getMethod() == HttpMethod.GET) {
|
||||
getTesterFlag(request, responseWriter);
|
||||
} else {
|
||||
throw new HttpProcessingException(404);
|
||||
}
|
||||
}
|
||||
|
||||
private void addTesterFlag(HttpRequest request, ResponseWriter responseWriter) throws Exception {
|
||||
HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request);
|
||||
try {
|
||||
Player player = getResourceOwnerSafely(request, null);
|
||||
|
||||
_playerDAO.addPlayerFlag(player.getName(), "t");
|
||||
|
||||
responseWriter.writeHtmlResponse("OK");
|
||||
|
||||
} finally {
|
||||
postDecoder.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTesterFlag(HttpRequest request, ResponseWriter responseWriter) throws Exception {
|
||||
HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request);
|
||||
try {
|
||||
Player player = getResourceOwnerSafely(request, null);
|
||||
|
||||
_playerDAO.removePlayerFlag(player.getName(), "t");
|
||||
|
||||
responseWriter.writeHtmlResponse("OK");
|
||||
|
||||
} finally {
|
||||
postDecoder.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void getTesterFlag(HttpRequest request, ResponseWriter responseWriter) throws Exception {
|
||||
HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request);
|
||||
try {
|
||||
Player player = getResourceOwnerSafely(request, null);
|
||||
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document doc = documentBuilder.newDocument();
|
||||
Element hasTester = doc.createElement("hasTester");
|
||||
|
||||
hasTester.setAttribute("result", String.valueOf(player.getType().contains("t")));
|
||||
|
||||
responseWriter.writeXmlResponse(doc);
|
||||
|
||||
} finally {
|
||||
postDecoder.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,6 +33,7 @@ public class RootUriRequestHandler implements UriRequestHandler {
|
||||
private PlayerStatsRequestHandler _playerStatsRequestHandler;
|
||||
private TournamentRequestHandler _tournamentRequestHandler;
|
||||
private SoloDraftRequestHandler _soloDraftRequestHandler;
|
||||
private PlaytestRequestHandler _playtestRequestHandler;
|
||||
|
||||
private Pattern originPattern;
|
||||
|
||||
@@ -58,6 +59,7 @@ public class RootUriRequestHandler implements UriRequestHandler {
|
||||
_playerStatsRequestHandler = new PlayerStatsRequestHandler(context);
|
||||
_tournamentRequestHandler = new TournamentRequestHandler(context);
|
||||
_soloDraftRequestHandler = new SoloDraftRequestHandler(context);
|
||||
_playtestRequestHandler = new PlaytestRequestHandler(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,6 +112,10 @@ public class RootUriRequestHandler implements UriRequestHandler {
|
||||
_tournamentRequestHandler.handleRequest(uri.substring(_serverContextPath.length() + 10), request, context, responseWriter, remoteIp);
|
||||
} else if (uri.startsWith(_serverContextPath + "soloDraft")) {
|
||||
_soloDraftRequestHandler.handleRequest(uri.substring(_serverContextPath.length() + 9), request, context, responseWriter, remoteIp);
|
||||
|
||||
} else if (uri.startsWith(_serverContextPath + "playtesting")) {
|
||||
_playtestRequestHandler.handleRequest(uri.substring(_serverContextPath.length() + 11), request, context, responseWriter, remoteIp);
|
||||
|
||||
} else {
|
||||
throw new HttpProcessingException(404);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
|
||||
<audio id="gamestart" src="/gemp-lotr/fanfare_x.mp3" type="audio/mpeg" preload="metadata"></audio>
|
||||
|
||||
<style type="text/css">
|
||||
.highlight-new {
|
||||
background-color: #aa2222 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
var chat;
|
||||
var hall;
|
||||
@@ -168,6 +174,7 @@
|
||||
<li><a href="includes/contribute.html">Contribute</a></li>
|
||||
<li><a href="includes/yourStats.html">Your stats</a></li>
|
||||
<li><a href="includes/stats.html">Server stats</a></li>
|
||||
<li ><a class="highlight-new" href="includes/playtesting.html">Playtesting (new!)</a></li>
|
||||
<script type="text/javascript">
|
||||
document.write('<li><a href="includes/changeLog.html?_=' + (new Date().getTime()) + '">Change Log</a></li>');
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div style="width:max(800px, 50%); margin:auto; font-size: 125%">
|
||||
<p>The <a href="https://lotrtcgpc.net">Player's Council</a> is dedicated to cleaning up the game's fossilized meta, and we aim to do so both through errata of broken (or underperforming) cards and the introduction of new cards compatible with existing formats.</p>
|
||||
|
||||
<p>Although we spend weeks or months arguing the finer points of card balancing, there is no argument as powerful as the result of dedicated playtesting. Once a card has been developed to the point of requiring playtesting, we release it here on Gemp and unlock it within special hidden playtesting formats.</p>
|
||||
|
||||
<p>If you would like to help us do this by playing matches with these cards, then use the button below to enable the playtesting formats on your account! If later you decide you no longer want to see how the sausage is made, then return to this screen and click the disable button instead.</p>
|
||||
|
||||
<button id="btnEnableTesting" onclick="hall.AddTesterFlag()">Enable Playtesting</button>
|
||||
<button id="btnDisableTesting" onclick="hall.RemoveTesterFlag()">Disable Playtesting</button>
|
||||
|
||||
<p>After playing playtest games, you can leave feedback <a href="https://docs.google.com/forms/d/e/1FAIpQLSdKJrCmjoyUqDTusDcpNoWAmvkGdzQqTxWGpdNIFX9biCee-A/viewform?usp=pp_url">using this form here</a>.</p>
|
||||
|
||||
<p>If you have any questions or would like to discuss our card design decisions in-depth, then feel free to join us <a href="https://lotrtcgpc.net/discord">on the PC Discord server</a>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.status {
|
||||
.status, .error {
|
||||
margin: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
@@ -615,6 +615,33 @@ var GempLotrCommunication = Class.extend({
|
||||
dataType:"html"
|
||||
});
|
||||
},
|
||||
|
||||
addTesterFlag:function (callback, errorMap) {
|
||||
$.ajax({
|
||||
type:"POST",
|
||||
url:this.url + "/playtesting/addTesterFlag",
|
||||
cache:false,
|
||||
data:{
|
||||
participantId:getUrlParam("participantId")},
|
||||
success:this.deliveryCheck(callback),
|
||||
error:this.errorCheck(errorMap),
|
||||
dataType:"html"
|
||||
});
|
||||
},
|
||||
|
||||
removeTesterFlag:function (callback, errorMap) {
|
||||
$.ajax({
|
||||
type:"POST",
|
||||
url:this.url + "/playtesting/removeTesterFlag",
|
||||
cache:false,
|
||||
data:{
|
||||
participantId:getUrlParam("participantId")},
|
||||
success:this.deliveryCheck(callback),
|
||||
error:this.errorCheck(errorMap),
|
||||
dataType:"html"
|
||||
});
|
||||
},
|
||||
|
||||
getStatus:function (callback, errorMap) {
|
||||
$.ajax({
|
||||
type:"GET",
|
||||
|
||||
@@ -402,6 +402,22 @@ var GempLotrHallUI = Class.extend({
|
||||
var myAudio = document.getElementById(soundObj);
|
||||
myAudio.play();
|
||||
},
|
||||
|
||||
AddTesterFlag: function() {
|
||||
var that = this;
|
||||
|
||||
that.comm.addTesterFlag(function () {
|
||||
window.location.reload(true);
|
||||
});
|
||||
},
|
||||
|
||||
RemoveTesterFlag: function() {
|
||||
var that = this;
|
||||
|
||||
that.comm.removeTesterFlag(function () {
|
||||
window.location.reload(true);
|
||||
});
|
||||
},
|
||||
|
||||
processHall:function (xml) {
|
||||
var that = this;
|
||||
@@ -698,7 +714,10 @@ var GempLotrHallUI = Class.extend({
|
||||
for (var i = 0; i < formats.length; i++) {
|
||||
var format = formats[i].childNodes[0].nodeValue;
|
||||
var type = formats[i].getAttribute("type");
|
||||
this.supportedFormatsSelect.append("<option value='" + type + "'>" + format + "</option>");
|
||||
|
||||
var item = "<option value='" + type + "'>" + format + "</option>"
|
||||
|
||||
this.supportedFormatsSelect.append(item);
|
||||
}
|
||||
this.supportedFormatsInitialized = true;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,22 @@ public class CachedPlayerDAO implements PlayerDAO, Cached {
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPlayerFlag(String login, String flag) throws SQLException {
|
||||
final boolean success = _delegate.addPlayerFlag(login, flag);
|
||||
if (success)
|
||||
clearCache();
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePlayerFlag(String login, String flag) throws SQLException {
|
||||
final boolean success = _delegate.removePlayerFlag(login, flag);
|
||||
if (success)
|
||||
clearCache();
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Player> findSimilarAccounts(String login) throws SQLException {
|
||||
return _delegate.findSimilarAccounts(login);
|
||||
|
||||
@@ -106,6 +106,30 @@ public class DbPlayerDAO implements PlayerDAO {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPlayerFlag(String login, String flag) throws SQLException {
|
||||
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
|
||||
try (PreparedStatement statement = conn.prepareStatement("UPDATE player SET type = CONCAT(type, ?) WHERE name=? AND type NOT LIKE CONCAT('%', ?, '%');")) {
|
||||
statement.setString(1, flag);
|
||||
statement.setString(2, login);
|
||||
statement.setString(3, flag);
|
||||
return statement.executeUpdate() == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePlayerFlag(String login, String flag) throws SQLException {
|
||||
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
|
||||
try (PreparedStatement statement = conn.prepareStatement("UPDATE player SET type = REPLACE(type, ?, '') WHERE name=? AND type LIKE CONCAT('%', ?, '%');")) {
|
||||
statement.setString(1, flag);
|
||||
statement.setString(2, login);
|
||||
statement.setString(3, flag);
|
||||
return statement.executeUpdate() == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player loginUser(String login, String password) throws SQLException {
|
||||
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
|
||||
|
||||
@@ -16,6 +16,9 @@ public interface PlayerDAO {
|
||||
|
||||
public boolean unBanPlayer(String login) throws SQLException;
|
||||
|
||||
public boolean addPlayerFlag(String login, String flag) throws SQLException;
|
||||
public boolean removePlayerFlag(String login, String flag) throws SQLException;
|
||||
|
||||
public List<Player> findSimilarAccounts(String login) throws SQLException;
|
||||
|
||||
public Player loginUser(String login, String password) throws SQLException;
|
||||
|
||||
@@ -429,27 +429,30 @@
|
||||
},
|
||||
|
||||
{
|
||||
"name":"PLAYTEST - PC-FOTR",
|
||||
"name":"PLAYTEST - PC Fellowship Block",
|
||||
"code":"test_pc_fotr_block",
|
||||
"sites":"FELLOWSHIP",
|
||||
"cancelRingBearerSkirmish":true,
|
||||
"hall":true,
|
||||
"playtest":true,
|
||||
"set":[1, 2, 3, 51, 52, 53, 73, 74, 75, 101, 151],
|
||||
"banned":["1_40","1_311","2_32","3_42","3_68",]
|
||||
},
|
||||
{
|
||||
"name":"PLAYTEST - PC-Movie",
|
||||
"name":"PLAYTEST - PC Movie Block",
|
||||
"code":"test_pc_movie",
|
||||
"sites":"KING",
|
||||
"hall":true,
|
||||
"playtest":true,
|
||||
"set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 51, 52, 53, 73, 74, 75, 101, 151],
|
||||
"banned":["1_40","1_311","2_32","3_42","3_68", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "3_106", "3_108", "3_38", "3_67", "7_49", "7_96", "8_1", "10_2", "10_91"],
|
||||
},
|
||||
{
|
||||
"name":"PLAYTEST - PC-Expanded",
|
||||
"name":"PLAYTEST - PC Expanded",
|
||||
"code":"test_pc_expanded",
|
||||
"sites":"SHADOWS",
|
||||
"hall":true,
|
||||
"playtest":true,
|
||||
"banned":["1_40","1_311","2_32","3_42","3_68","1_45", "1_138", "1_234", "1_313", "1_316", "2_121", "3_17", "3_38", "3_67", "3_108", "3_113", "4_73", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"],
|
||||
"restricted":["1_80", "1_108", "1_139", "1_195", "1_248", "2_75", "3_106", "4_276", "4_304"],
|
||||
"set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 52, 53, 73, 74, 75, 101, 151]
|
||||
|
||||
Reference in New Issue
Block a user