Added Help -> PC Errata screen, which permits the user to see each PC errata side-by-side with the original

This commit is contained in:
Christian 'ketura' McCarty
2022-12-12 00:28:00 -06:00
parent 317a8f30ff
commit 8022f891fb
14 changed files with 250 additions and 12 deletions

View File

@@ -12,7 +12,7 @@ public interface ResponseWriter {
public void writeFile(File file, Map<String, String> headers);
public void writeHtmlResponse(String html);
public void writeJsonResponse(String html);
public void writeJsonResponse(String json);
public void writeByteResponse(byte[] bytes, Map<? extends CharSequence, String> headers);

View File

@@ -1,5 +1,6 @@
package com.gempukku.lotro.async.handler;
import com.alibaba.fastjson.JSON;
import com.gempukku.lotro.SubscriptionConflictException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.async.HttpProcessingException;
@@ -65,6 +66,8 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
updateHall(request, responseWriter);
} else if (uri.equals("/formats/html") && request.method() == HttpMethod.GET) {
getFormats(request, responseWriter);
} else if (uri.equals("/errata/json") && request.method() == HttpMethod.GET) {
getErrataInfo(request, responseWriter);
} else if (uri.startsWith("/format/") && request.method() == HttpMethod.GET) {
getFormat(request, uri.substring(8), responseWriter);
} else if (uri.startsWith("/queue/") && request.method() == HttpMethod.POST) {
@@ -340,6 +343,14 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
}
}
private void getErrataInfo(HttpRequest request, ResponseWriter responseWriter) throws CardNotFoundException {
var errata = _library.getErrata();
String json = JSON.toJSONString(errata);
responseWriter.writeJsonResponse(json);
}
private void getHall(HttpRequest request, ResponseWriter responseWriter) {
QueryStringDecoder queryDecoder = new QueryStringDecoder(request.uri());

View File

@@ -55,6 +55,22 @@ body {
font-size: 70%;
}
button.navigation-butt {
padding: 0.5em;
}
.navigation-butt.ui-button-icon-only > .ui-button-text{
padding: 0;
}
.navigation-butt.ui-button-icon-only {
width: 25px;
}
.ui-button-icon-only .ui-button-icon-primary.ui-icon {
margin: auto auto auto -4px;
}
#set {
width: 120px;
}

View File

@@ -172,6 +172,11 @@ button {
opacity: 0.3;
}*/
.cultureHint {
position:relative;
top: 4px;
}
#gameHall {
overflow-y: scroll;
width: calc(100% );

View File

@@ -89,7 +89,8 @@
autoOpen:false,
closeOnEscape:true,
resizable:false,
title:"Card information"
title:"Card information",
closeText: ""
});
$("body").click(
@@ -97,13 +98,20 @@
var tar = $(event.target);
if (tar.hasClass("cardHint")) {
var blueprintId = tar.attr("value");
var card = new Card(blueprintId, "SPECIAL", "hint", "");
var ids = tar.attr("value").split(",");
infoDialog.html("");
infoDialog.html("<div style='scroll: auto'></div>");
var floatCardDiv = $("<div style='float: left;'></div>");
floatCardDiv.append(createFullCardDiv(card.imageUrl, card.foil, card.horizontal));
var floatCardDiv = $("<div style='float: left; display:flex; gap: 5px;'></div>");
var horiz = false;
for(var i = 0; i < ids.length; i++) {
var bpid = ids[i];
var card = new Card(bpid, "SPECIAL", "hint", "");
horiz = horiz || card.horizontal;
floatCardDiv.append(createFullCardDiv(card.imageUrl, card.foil, card.horizontal));
}
infoDialog.append(floatCardDiv);
var windowWidth = $(window).width();
@@ -111,14 +119,21 @@
var horSpace = 30;
var vertSpace = 45;
var height = 505;
var width = 340;
infoDialog.dialog({title:"Card information"});
if (card.horizontal) {
infoDialog.dialog({
title:"Card information",
});
if (horiz) {
// 500x360
infoDialog.dialog({width:Math.min(500 + horSpace, windowWidth), height:Math.min(360 + vertSpace, windowHeight)});
infoDialog.dialog({width:Math.min((height + 10) * ids.length, windowWidth),
height:Math.min((width + 90), windowHeight)});
} else {
// 360x500
infoDialog.dialog({width:Math.min(360 + horSpace, windowWidth), height:Math.min(500 + vertSpace, windowHeight)});
infoDialog.dialog({width:Math.min((width + 30) * ids.length, windowWidth),
height:Math.min((height + 45), windowHeight)});
}
infoDialog.dialog("open");
@@ -325,7 +340,7 @@
<label style="min-width: fit-content;"><input type='checkbox' id='isPrivateCheckbox'>Invite Only</input></label>
<button id="createTableBut">Create table</button>
</div>
<div id="chat" class=" flex-horiz" >
<div id="chat" class="flex-horiz" >
<div id="chatarea" class="flex-vert">
<div id="legacyChat" class="flex-vert">
<div id="chatMessages" class="flex-vert"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" viewBox="0 -410 2121 2122" id="svg6" sodipodi:docname="site.svg" width="2121" height="2122" inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<metadata id="metadata12">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs10"/>
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview8" showgrid="false" inkscape:zoom="0.30712891" inkscape:cx="174.87838" inkscape:cy="1064.7552" inkscape:current-layer="svg6"/>
<g transform="matrix(1,0,0,-1,-50,1401)" id="g4">
<path d="M 2171,750 1861,439 V 0 H 1421 L 1111,-311 800,0 H 361 V 439 L 50,750 361,1061 v 439 h 439 l 311,311 310,-311 h 440 V 1061 Z M 436,364 V 75 H 725 Z M 725,1425 H 436 v -289 z m 1061,-289 v 289 H 1496 Z M 1786,75 V 364 L 1496,75 Z M 906,0 1111,-205 1315,0 Z M 361,955 156,750 361,545 Z m 954,545 -204,205 -205,-205 z m 471,-470 -396,395 H 831 L 436,1030 V 470 L 831,75 h 559 l 396,395 z M 2065,750 1861,955 V 545 Z m -737,0 q 0,-90 -63.5,-154 -63.5,-64 -153.5,-64 -90,0 -154,64 -64,64 -64,154 0,90 64,153.5 64,63.5 154,63.5 90,0 153.5,-63.5 Q 1328,840 1328,750 Z m -75,0 q 0,59 -42,100.5 -42,41.5 -101,41.5 -59,0 -100.5,-41.5 Q 968,809 968,750 q 0,-59 41.5,-101 41.5,-42 100.5,-42 59,0 101,42 42,42 42,101 z" id="path2" inkscape:connector-curvature="0" style="fill:currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -15,6 +15,7 @@
<li><a href="includes/help/coc.html">Code of Conduct</a></li>
<li><a href="includes/help/formatRules.html">Format Rules</a></li>
<li><a href="includes/help/leagueRules.html">League Rules</a></li>
<li><a href="includes/help/pc-errata.html">PC Errata</a></li>
</ol>
</div>
<div id="howtoplay">

View File

@@ -0,0 +1,75 @@
<div id="formats">
<script>
$("#helpMain").ready(
function () {
hall.comm.getErrata(function(json){
//$("#errata-readout").text(JSON.stringify(json, null, 2));
var top = $("<div style='display:flex; flex-direction:column; gap:20px; justify-content:center; align-items:center;'></div>");
var results = {};
for(var bp in json) {
var info = json[bp];
var eid = info.ErrataIDs.PC;
var text = info.LinkText;
text = text.replace(eid, bp + "," + eid);
//console.log(text);
//result.append(text);
var parts = bp.split("_");
var setID = parseInt(parts[0]);
var cardID = parseInt(parts[1]);
if(setID in results) {
results[setID][cardID] = text;
}
else {
results[setID] = {};
results[setID][cardID] = text;
}
}
//debugger;
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var sets = Object.keys(results).sort(collator.compare);
for(var set in sets) {
var setdiv = $("<div style='display:flex; flex-direction:column; gap:10px; flex-wrap: wrap; width:70%; row-gap:10px; column-gap:30px; '></div>");
top.append($("<div style='margin:auto; font-size: 140%; position:relative; top:20px; bottom:10px;'>Set " + sets[set] + "</div>"));
//(# * 28) / 2
//debugger;
var cards = Object.keys(results[sets[set]]).sort(collator.compare);
for(var card in cards) {
var cardspan = $("<span></span>");
var html = results[sets[set]][cards[card]];
cardspan.append(results[sets[set]][cards[card]]);
setdiv.append(cardspan);
}
setdiv.css({"height": "" + (((cards.length * 28) / 1.8) + 30) + "px"});
top.append(setdiv);
}
$("#errata-readout").html(top);
}, hall.hallErrorMap());
}
);
</script>
<div id="errata-info" class="article">
<p>
All errata are indicated in-game with a red slash in their upper-right-hand corner. Errata that were issued by the Player's Council instead of Decipher also have this slash, but also include the errata date in the lower-left-hand corner of the card.
<p>
Each of the released errata have had a full writeup on the PC's thoughts and justifications <a href="https://wiki.lotrtcgpc.net/wiki/PC_Errata">here on the LOTR-TCG wiki</a>.
</p>
<p>
Below you can find a quick reference allowing you to quickly compare released errata.
</p>
<div id="errata-readout" />
</div>
</div>

View File

@@ -684,6 +684,19 @@ var GempLotrCommunication = Class.extend({
});
},
getErrata:function (callback, errorMap) {
$.ajax({
type:"GET",
url:this.url + "/hall/errata/json",
cache:false,
data:{
participantId:getUrlParam("participantId")},
success:this.deliveryCheck(callback),
error:this.errorCheck(errorMap),
dataType:"json"
});
},
addTesterFlag:function (callback, errorMap) {
$.ajax({
type:"POST",

View File

@@ -64,4 +64,13 @@ public class JSONDefs {
public Map<String, SealedTemplate> SealedTemplates;
public Map<String, ItemStub> DraftTemplates;
}
public static class ErrataInfo {
public static String PC_Errata = "PC";
public String BaseID;
public String Name;
public String LinkText;
public Map<String, String> ErrataIDs;
}
}

View File

@@ -3,8 +3,10 @@ package com.gempukku.lotro.game;
import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
import com.gempukku.lotro.cards.build.LotroCardBlueprintBuilder;
import com.gempukku.lotro.common.AppConfig;
import com.gempukku.lotro.common.JSONDefs;
import com.gempukku.lotro.game.packs.DefaultSetDefinition;
import com.gempukku.lotro.game.packs.SetDefinition;
import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.util.JsonUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
@@ -91,6 +93,8 @@ public class LotroCardBlueprintLibrary {
reloadSets();
reloadMappings();
reloadCards();
errataMappings = null;
getErrata();
for(var callback : _refreshCallbacks) {
callback.Invoke();
@@ -302,6 +306,53 @@ public class LotroCardBlueprintLibrary {
}
}
private Map<String, JSONDefs.ErrataInfo> errataMappings = null;
public Map<String, JSONDefs.ErrataInfo> getErrata() {
try {
if(errataMappings == null) {
collectionReady.acquire();
errataMappings = new HashMap<>();
for (String id : _blueprints.keySet()) {
var parts = id.split("_");
int setID = Integer.parseInt(parts[0]);
String cardID = parts[1];
JSONDefs.ErrataInfo card = null;
String base = id;
if(setID >= 50 && setID <= 69) {
base = "" + (setID - 50) + "_" + cardID;
}
else if(setID >= 70 && setID <= 89) {
base = "" + (setID - 70) + "_" + cardID;
}
else if(setID >= 150 && setID <= 199) {
base = "" + (setID - 50) + "_" + cardID;
}
else
continue;
if(errataMappings.containsKey(base)) {
card = errataMappings.get(base);
}
else {
card = new JSONDefs.ErrataInfo();
card.BaseID = base;
card.Name = GameUtils.getFullName(_blueprints.get(base));
card.LinkText = GameUtils.getDeluxeCardLink(id, _blueprints.get(base));
card.ErrataIDs = new HashMap<>();
errataMappings.put(base, card);
}
card.ErrataIDs.put(JSONDefs.ErrataInfo.PC_Errata, id);
}
collectionReady.release();
}
return errataMappings;
} catch (InterruptedException exp) {
throw new RuntimeException("LotroCardBlueprintLibrary.getErrata() interrupted: ", exp);
}
}
public boolean hasAlternateInSet(String blueprintId, int setNo) {
try {
collectionReady.acquire();

View File

@@ -116,6 +116,24 @@ public class GameUtils {
return "<div class='cardHint' value='" + blueprintId + "'>" + (blueprint.isUnique() ? "·" : "") + GameUtils.getFullName(blueprint) + "</div>";
}
public static String getDeluxeCardLink(String blueprintId, LotroCardBlueprint blueprint) {
var culture = blueprint.getCulture();
var cultureString = "";
if(culture == null) {
if (blueprint.getTitle().equals("The One Ring")) {
cultureString = getCultureImage(culture, "one_ring");
}
else {
cultureString = getCultureImage(culture, "site");
}
}
else {
cultureString = getCultureImage(culture, null);
}
return "<div class='cardHint' value='" + blueprintId + "'>" + cultureString
+ (blueprint.isUnique() ? "·" : "") + " " + GameUtils.getFullName(blueprint) + "</div>";
}
public static String getCultureImage(String cultureName) {
Culture culture = Culture.findCulture(cultureName);
if(culture == null)
@@ -124,6 +142,13 @@ public class GameUtils {
return getCultureImage(culture);
}
public static String getCultureImage(Culture culture, String override) {
if(override == null || override.isEmpty()) {
override = culture.toString().toLowerCase();
}
return "<span class='cultureHint' ><img src='images/cultures/" + override + ".png'></span>";
}
public static String getCultureImage(Culture culture) {
return "<span class='cultureHint' value='" + culture.toString() + "'><img src='images/cultures/" + culture.toString().toLowerCase() + ".png'> "
+ culture.getHumanReadable() + "</span>";