New Content - Implemented Deck of Every Card

The text from acquiring the VIP Key in standard.

Code:
<body>
<div id='menu' class=rcm></div><script>parent.menupane.location.href="topmenu.php";</script><center></center><center><center><table width=95% cellspacing=0 cellpadding=0><tr><td style="color: white;" align=center bgcolor=orange><b>New Events:</b></td></tr><tr><td style="padding: 5px; border: 1px solid orange;" align=center>07/24/15 05:34 PM - <font color=green>Loading "inventory.php?which=3".<!--js(top.mainpane.location='inventory.php?which=3')--></font><br><br />07/24/15 07:21 PM - <font color=green><a target=mainpane href="messages.php?box=PvP"><a style="color: green;" target="mainpane" href="showplayer.php?who=516993">cyborgstan</a><a style="color: green;" target="mainpane" href="peevpee.php?action=log&lid=463023&place=logs"> just attacked you!</a></a></font><br><br />07/24/15 07:45 PM - <a href=main.php target=mainpane class=error>Click here to continue in the relay browser.</a><br><br />07/24/15 08:21 PM - <font color=green><a target=mainpane href="messages.php?box=PvP"><a style="color: green;" target="mainpane" href="showplayer.php?who=307643">SyrinxLui</a><a style="color: green;" target="mainpane" href="peevpee.php?action=log&lid=463381&place=logs"> just attacked you!</a></a></font><br><br />07/24/15 08:51 PM - <font color=green>Using 1 photocopied monster.<!--js(dojax('inv_use.php?whichitem=4873&ajax=1&pwd=75a4fb630e71f3c243ab7db0883ec9b4');)--></font><br><br />07/24/15 08:56 PM - <font color=green><a target=mainpane href="messages.php">New message received from Planet Xi.</a></font><br><br />07/24/15 08:56 PM - <font color=green><a target=mainpane href="messages.php">New message received from The Loathing Postal Service.</a></font><br><br />07/24/15 12:57:00 PM - Welcome back to the Kingdom of Loathing.  Noob.<br /><p>You remember you have a lifetime VIP membership and grab your key!<center><table class="item" style="float: none" rel="id=3947&s=0&q=0&d=0&g=0&t=0&n=1&m=0&p=0&u=."><tr><td><img src="/images/itemimages/vipkey.gif" alt="Clan VIP Lounge key" title="Clan VIP Lounge key" class=hand onClick='descitem(889601925)'></td><td valign=center class=effect>You acquire an item: <b>Clan VIP Lounge key</b></td></tr><tr><td height=4></td></tr></table></center><table  width=95%  cellspacing=0 cellpadding=0><tr><td style="color: white;" align=center bgcolor=blue><b>The Kingdom of Loathing</b></td></tr><tr><td style="padding: 5px; border: 1px solid blue;"><center><table><tr><td><center><table cellpadding=0 cellspacing=0><tr><td colspan=6><img src="/images/otherimages/main/main_top.gif" width=350 height=50 alt="Top Edge" title="Top Edge"></td></tr><tr><td rowspan=3><img src="/images/otherimages/main/main_left.gif" width=25 height=300 alt="Left Edge" title="Left Edge"></td><td colspan=2 width=100 height=100><a href="town.php"><img src="/images/otherimages/main/newmap1new.gif" width=100 height=100 border=0 alt="Seaside Town" title="Seaside Town"></a></td><td width=100 height=100><a href="campground.php"><img src="/images/otherimages/main/map2.gif" width=100 height=100 border=0 alt="The Campground" title="The Campground"></a></td><td width=100 height=100><a href="mountains.php"><img src="/images/otherimages/main/map3.gif" width=100 height=100 border=0 alt="The Big Mountains" title="The Big Mountains"></a></td><td rowspan=3><img src="/images/otherimages/main/main_right.gif" width=25 height=300 alt="Right Edge" title="Right Edge"></td></tr><tr><td width=50 height=100><img src=/images/otherimages/main/map4a.gif width=50 height=100 alt="Nothing" title="Nothing"></td><td width=50 height=100><a href=oldman.php><img src=/images/otherimages/main/map4b.gif width=50 height=100 border=0 alt="A seaside shack" title="A seaside shack"></a></td><td width=100 height=100><a href="place.php?whichplace=plains"><img src="/images/otherimages/main/map5.gif" width=100 height=100 border=0 alt="The Nearby Plains" title="The Nearby Plains"></a></td><td width=100 height=100><A href=place.php?whichplace=nstower><img src=/images/otherimages/main/newmap6.gif width=100 height=100 border=0 alt="The Lair of the Naughty Sorceress" title="The Lair of the Naughty Sorceress"></a></td></tr><tr><td width=100 colspan=2 height=100><img src="/images/otherimages/main/map7.gif" width=100 height=100 border=0 alt="Nothing" title="Nothing"></td><td width=100 height=100><img src="/images/otherimages/main/map8blank.gif" width=100 height=100 alt="Nothing" title="Nothing"></td><td width=100 height=100><img src="/images/otherimages/main/map9.gif" width=100 height=100 border=0 alt="Nothing" title="Nothing"></td></tr><tr><td colspan=6><img src="/images/otherimages/main/main_bottom.gif" width=350 height=50 border=0 alt="Bottom Edge" title="Bottom Edge"></td></tr></table></td></tr></table></center></td></tr><tr><td height=4></td></tr></table></center></body><script src="/onfocus.1.js"></script></html>
 
That text does not match EventManager.EVENT_PATTERN. The following patch will make EventManager recognize your text:

Code:
Index: src/net/sourceforge/kolmafia/RequestEditorKit.java
===================================================================
--- src/net/sourceforge/kolmafia/RequestEditorKit.java	(revision 16065)
+++ src/net/sourceforge/kolmafia/RequestEditorKit.java	(working copy)
@@ -654,14 +654,13 @@
 			}
 		}
 
-		Matcher eventMatcher = EventManager.EVENT_PATTERN.matcher( buffer.toString() );
-		boolean showingEvents = eventMatcher.find();
+		Matcher eventMatcher = EventManager.eventMatcher( buffer.toString() );
 
-		if ( EventManager.hasEvents() && ( showingEvents || location.contains( "main.php" ) ) )
+		if ( EventManager.hasEvents() && ( eventMatcher != null || location.contains( "main.php" ) ) )
 		{
 			int eventTableInsertIndex = 0;
 
-			if ( showingEvents )
+			if ( eventMatcher != null )
 			{
 				eventTableInsertIndex = eventMatcher.start();
 
Index: src/net/sourceforge/kolmafia/session/EventManager.java
===================================================================
--- src/net/sourceforge/kolmafia/session/EventManager.java	(revision 16065)
+++ src/net/sourceforge/kolmafia/session/EventManager.java	(working copy)
@@ -58,11 +58,30 @@
 	private static final LockableListModel<String> eventTexts = new LockableListModel<String>();
 	private static final LockableListModel<String> eventHyperTexts = new LockableListModel<String>();
 
-	public static final Pattern EVENT_PATTERN =
+	public static final Pattern EVENT_PATTERN1 =
 		Pattern.compile( "<table[^>]*><tr><td[^>]*bgcolor=orange><b>New Events:</b></td></tr><tr><td style=\"padding: 5px; border: 1px solid orange;\"><center><table><tr><td>(.*?)</td></tr></table>.*?<td height=4></td></tr></table>" );
 
+	public static final Pattern EVENT_PATTERN2 =
+		Pattern.compile( "<table[^>]*><tr><td[^>]*bgcolor=orange><b>New Events:</b></td></tr><tr><td style=\"padding: 5px; border: 1px solid orange;\" align=center>(.*?)</td></tr><tr><td height=4></td></tr></table>" );
+
 	private static final SimpleDateFormat EVENT_TIMESTAMP = new SimpleDateFormat( "MM/dd/yy hh:mm a", Locale.US );
 
+	public static Matcher eventMatcher( final String responseText )
+	{
+		Matcher matcher = EventManager.EVENT_PATTERN1.matcher( responseText );
+		if ( matcher.find() )
+		{
+			return matcher;
+		}
+
+		matcher = EventManager.EVENT_PATTERN2.matcher( responseText );
+		if ( matcher.find() )
+		{
+			return matcher;
+		}
+		return null;
+	}
+
 	public static boolean hasEvents()
 	{
 		return !EventManager.eventTexts.isEmpty();
@@ -178,31 +197,27 @@
 		// Capture the entire new events table in order to display the
 		// appropriate message.
 
-		Matcher eventMatcher = EventManager.EVENT_PATTERN.matcher( responseText );
-		if ( !eventMatcher.find() )
+		Matcher eventMatcher = EventManager.eventMatcher( responseText );
+		if ( eventMatcher == null )
 		{
 			return;
 		}
 
 		// Make an array of events
-
 		String[] events = eventMatcher.group( 1 ).replaceAll( "<br>", "\n" ).split( "\n" );
 
-		for ( int i = 0; i < events.length; ++i )
+		for ( String event : events )
 		{
-			if ( events[ i ].indexOf( "/" ) == -1 )
+			if ( !event.contains( "/" ) )
 			{
-				events[ i ] = null;
+				continue;
 			}
-		}
 
-		for ( int i = 0; i < events.length; ++i )
-		{
-			EventManager.addNormalEvent( events[ i ] );
+			EventManager.addNormalEvent( event );
 
 			if ( ChatManager.isRunning() )
 			{
-				ChatManager.broadcastEvent( new EventMessage( events[i], "green" ) );
+				ChatManager.broadcastEvent( new EventMessage( event, "green" ) );
 			}
 		}
 	}
Index: src/net/sourceforge/kolmafia/textui/command/TestCommand.java
===================================================================
--- src/net/sourceforge/kolmafia/textui/command/TestCommand.java	(revision 16065)
+++ src/net/sourceforge/kolmafia/textui/command/TestCommand.java	(working copy)
@@ -94,6 +94,7 @@
 import net.sourceforge.kolmafia.session.ChoiceManager;
 import net.sourceforge.kolmafia.session.DadManager;
 import net.sourceforge.kolmafia.session.DvorakManager;
+import net.sourceforge.kolmafia.session.EventManager;
 import net.sourceforge.kolmafia.session.ResultProcessor;
 import net.sourceforge.kolmafia.session.ResponseTextParser;
 import net.sourceforge.kolmafia.session.RumpleManager;
@@ -660,6 +661,13 @@
 			return;
 		}
 
+		if ( command.equals( "events" ) )
+		{
+			EventManager.checkForNewEvents( TestCommand.contents );
+			TestCommand.contents = null;
+			return;
+		}
+
 		if ( command.equals( "fight" ) )
 		{
 			int round = split.length > 1 ? StringUtilities.parseInt( split[ 1 ].trim() ) : -1;
So, what I see is bunch of one-line events:

Code:
07/24/15 05:34 PM - <font color=green>Loading "inventory.php?which=3".<!--js(top.mainpane.location='inventory.php?which=3')--></font>
<br />07/24/15 07:21 PM - <font color=green><a target=mainpane href="messages.php?box=PvP"><a style="color: green;" target="mainpane" href="showplayer.php?who=516993">cyborgstan</a><a style="color: green;" target="mainpane" href="peevpee.php?action=log&lid=463023&place=logs"> just attacked you!</a></a></font>
<br />07/24/15 07:45 PM - <a href=main.php target=mainpane class=error>Click here to continue in the relay browser.</a>
<br />07/24/15 08:21 PM - <font color=green><a target=mainpane href="messages.php?box=PvP"><a style="color: green;" target="mainpane" href="showplayer.php?who=307643">SyrinxLui</a><a style="color: green;" target="mainpane" href="peevpee.php?action=log&lid=463381&place=logs"> just attacked you!</a></a></font>
<br />07/24/15 08:51 PM - <font color=green>Using 1 photocopied monster.<!--js(dojax('inv_use.php?whichitem=4873&ajax=1&pwd=75a4fb630e71f3c243ab7db0883ec9b4');)--></font>
<br />07/24/15 08:56 PM - <font color=green><a target=mainpane href="messages.php">New message received from Planet Xi.</a></font>
<br />07/24/15 08:56 PM - <font color=green><a target=mainpane href="messages.php">New message received from The Loathing Postal Service.</a></font>
<br />07/24/15 12:57:00 PM - Welcome back to the Kingdom of Loathing.  Noob.<br />
... all of which have a timestamp at the front, and hence are processed as "events", since they have a "/", with the following HTML glommed onto the end of the table:

Code:
<p>You remember you have a lifetime VIP membership and grab your key!<center><table class="item" style="float: none" rel="id=3947&s=0&q=0&d=0&g=0&t=0&n=1&m=0&p=0&u=."><tr><td><img src="/images/itemimages/vipkey.gif" alt="Clan VIP Lounge key" title="Clan VIP Lounge key" class=hand onClick='descitem(889601925)'></td><td valign=center class=effect>You acquire an item: <b>Clan VIP Lounge key</b>
... which has no timestamp, but which will still be processed as an "event" since it, too, has a "/" - even though it's not a timestamp.

EventManager.addNormalEvent will take that and remove all the links ("a" and "/a" tags), but will retain all the other tags.

I might suggest that EventManager.checkFrNewEvents might do this:

After matching the event section (using the modified code I gave above), rather than splitting eventMatcher.group(1) into lines, split it at the "p" tag (if any). Those line which come before are normal "events". That which comes after is the VIP key - and presumably the Deck of Every Card - and needs to be split up a different way.

I'll play a little bit more with this, but I don't expect to ascend again before the next challenge path starts, so I will not be the one to finish this.

It'd be nice to see what happens when you get both a VIP key and the Deck.
 
Last edited:
OK, by splitting the events into two parts - that which precedes the "p" tag" and whatever follows - and only processing the former, I got this:

> test load events.html

Read 4,841 bytes into a 4,841 character string

> test events

07/24/15 05:34 PM - Loading "inventory.php?which=3".
07/24/15 07:21 PM - cyborgstan just attacked you!
07/24/15 07:45 PM - Click here to continue in the relay browser.
07/24/15 08:21 PM - SyrinxLui just attacked you!
07/24/15 08:51 PM - Using 1 photocopied monster.
07/24/15 08:56 PM - New message received from Planet Xi.
07/24/15 08:56 PM - New message received from The Loathing Postal Service.
07/24/15 12:57:00 PM - Welcome back to the Kingdom of Loathing. Noob.
It's be nice to process the "p" part of the events, too, but that's a job for another time...

Here's a diff:

Code:
Index: src/net/sourceforge/kolmafia/RequestEditorKit.java
===================================================================
--- src/net/sourceforge/kolmafia/RequestEditorKit.java	(revision 16065)
+++ src/net/sourceforge/kolmafia/RequestEditorKit.java	(working copy)
@@ -654,14 +654,13 @@
 			}
 		}
 
-		Matcher eventMatcher = EventManager.EVENT_PATTERN.matcher( buffer.toString() );
-		boolean showingEvents = eventMatcher.find();
+		Matcher eventMatcher = EventManager.eventMatcher( buffer.toString() );
 
-		if ( EventManager.hasEvents() && ( showingEvents || location.contains( "main.php" ) ) )
+		if ( EventManager.hasEvents() && ( eventMatcher != null || location.contains( "main.php" ) ) )
 		{
 			int eventTableInsertIndex = 0;
 
-			if ( showingEvents )
+			if ( eventMatcher != null )
 			{
 				eventTableInsertIndex = eventMatcher.start();
 
Index: src/net/sourceforge/kolmafia/session/EventManager.java
===================================================================
--- src/net/sourceforge/kolmafia/session/EventManager.java	(revision 16065)
+++ src/net/sourceforge/kolmafia/session/EventManager.java	(working copy)
@@ -58,11 +58,30 @@
 	private static final LockableListModel<String> eventTexts = new LockableListModel<String>();
 	private static final LockableListModel<String> eventHyperTexts = new LockableListModel<String>();
 
-	public static final Pattern EVENT_PATTERN =
+	public static final Pattern EVENT_PATTERN1 =
 		Pattern.compile( "<table[^>]*><tr><td[^>]*bgcolor=orange><b>New Events:</b></td></tr><tr><td style=\"padding: 5px; border: 1px solid orange;\"><center><table><tr><td>(.*?)</td></tr></table>.*?<td height=4></td></tr></table>" );
 
+	public static final Pattern EVENT_PATTERN2 =
+		Pattern.compile( "<table[^>]*><tr><td[^>]*bgcolor=orange><b>New Events:</b></td></tr><tr><td style=\"padding: 5px; border: 1px solid orange;\" align=center>(.*?)</td></tr><tr><td height=4></td></tr></table>" );
+
 	private static final SimpleDateFormat EVENT_TIMESTAMP = new SimpleDateFormat( "MM/dd/yy hh:mm a", Locale.US );
 
+	public static Matcher eventMatcher( final String responseText )
+	{
+		Matcher matcher = EventManager.EVENT_PATTERN1.matcher( responseText );
+		if ( matcher.find() )
+		{
+			return matcher;
+		}
+
+		matcher = EventManager.EVENT_PATTERN2.matcher( responseText );
+		if ( matcher.find() )
+		{
+			return matcher;
+		}
+		return null;
+	}
+
 	public static boolean hasEvents()
 	{
 		return !EventManager.eventTexts.isEmpty();
@@ -178,31 +197,35 @@
 		// Capture the entire new events table in order to display the
 		// appropriate message.
 
-		Matcher eventMatcher = EventManager.EVENT_PATTERN.matcher( responseText );
-		if ( !eventMatcher.find() )
+		Matcher eventMatcher = EventManager.eventMatcher( responseText );
+		if ( eventMatcher == null )
 		{
 			return;
 		}
 
 		// Make an array of events
+		String allEvents = eventMatcher.group( 1 );
+		int para = allEvents.indexOf( "<p>" );
+		String normalEvents = para == -1 ? allEvents : allEvents.substring( 0, para );
+		String otherEvents = para == -1 ? "" : allEvents.substring( para );
 
-		String[] events = eventMatcher.group( 1 ).replaceAll( "<br>", "\n" ).split( "\n" );
+		normalEvents = normalEvents.replaceAll( "<br />", "<br>" );
+		normalEvents = normalEvents.replaceAll( "<br>", "\n" );
 
-		for ( int i = 0; i < events.length; ++i )
+		String[] events = normalEvents.split( "\n" );
+
+		for ( String event : events )
 		{
-			if ( events[ i ].indexOf( "/" ) == -1 )
+			if ( !event.contains( "/" ) )
 			{
-				events[ i ] = null;
+				continue;
 			}
-		}
 
-		for ( int i = 0; i < events.length; ++i )
-		{
-			EventManager.addNormalEvent( events[ i ] );
+			EventManager.addNormalEvent( event );
 
 			if ( ChatManager.isRunning() )
 			{
-				ChatManager.broadcastEvent( new EventMessage( events[i], "green" ) );
+				ChatManager.broadcastEvent( new EventMessage( event, "green" ) );
 			}
 		}
 	}
Index: src/net/sourceforge/kolmafia/textui/command/TestCommand.java
===================================================================
--- src/net/sourceforge/kolmafia/textui/command/TestCommand.java	(revision 16065)
+++ src/net/sourceforge/kolmafia/textui/command/TestCommand.java	(working copy)
@@ -94,6 +94,7 @@
 import net.sourceforge.kolmafia.session.ChoiceManager;
 import net.sourceforge.kolmafia.session.DadManager;
 import net.sourceforge.kolmafia.session.DvorakManager;
+import net.sourceforge.kolmafia.session.EventManager;
 import net.sourceforge.kolmafia.session.ResultProcessor;
 import net.sourceforge.kolmafia.session.ResponseTextParser;
 import net.sourceforge.kolmafia.session.RumpleManager;
@@ -660,6 +661,13 @@
 			return;
 		}
 
+		if ( command.equals( "events" ) )
+		{
+			EventManager.checkForNewEvents( TestCommand.contents );
+			TestCommand.contents = null;
+			return;
+		}
+
 		if ( command.equals( "fight" ) )
 		{
 			int round = split.length > 1 ? StringUtilities.parseInt( split[ 1 ].trim() ) : -1;
 
Revision 16066 includes that change to event parsing. So, we should no longer display "You acquire an item", complete with images, in the gCLI, since we do not treat the un-timestamped HTML-tabled messages as Events, currently.

As I mentioned, somebody else should look into that...
 
I like the play/cheat command, but I'm having a hard time remembering some of the names, so I wrote a Daily Deed for the deck.
The code is more or less based on the drop-down for the clan shower, the cards are grouped by type, and their tool-tip summarizes what they actually do.

Oh, BTW, the help text for the play/cheat command is missing a leading space, so they show as "playrandom" and "cheatrandom".
 

Attachments

I like the play/cheat command, but I'm having a hard time remembering some of the names, so I wrote a Daily Deed for the deck.
The code is more or less based on the drop-down for the clan shower, the cards are grouped by type, and their tool-tip summarizes what they actually do.

Oh, BTW, the help text for the play/cheat command is missing a leading space, so they show as "playrandom" and "cheatrandom".

OK. I shot off my mouth and so am looking at this. If you don't get feedback PM me. The biggest question I have is what happens if if a card is drawn outside of the deed. Is the listener always active or only after the Daily Deeds panel is created?
 
The daily deed is pretty much nothing more than an interface to the "play" command. If you draw outside the deed, _deckCardsDrawn will change and any daily deeds panels that may be open will update the cards drawn count and reset the selection. If no such panels are active, I guess ... nothing happens?
 
The daily deed is pretty much nothing more than an interface to the "play" command. If you draw outside the deed, _deckCardsDrawn will change and any daily deeds panels that may be open will update the cards drawn count and reset the selection. If no such panels are active, I guess ... nothing happens?

Thanks.
 
For the case where the card is not available, there should be a soft halt rather than hard halt so scripts don't exit. If you already cheated once for a specific card, then the original goal for the function was already achieved and the script can continue without worry. I suppose this is just nitpicking since you can wrap it in a conditional statement.
 
The patch has passed my limited testing and I expect to commit it later "Today". This creates a built in Daily Deed that can be invoked from the Daily Deeds panel and removed from the panel via the Daily Deeds preferences, if desired.
 
r16164 adds Deck of Every Card to Daily Deeds as per PeKaJe's patch above. Lightly tested but seems to work.
 
Love the new Daily Deed. I'd been using a lazy Custom Deed that only allowed random draws (but, more importantly, showed me how many I had left). This is way better!

Thanks, PeKaJe and fronobulax.
 
Love the new Daily Deed. I'd been using a lazy Custom Deed that only allowed random draws (but, more importantly, showed me how many I had left). This is way better!

Thanks, PeKaJe and fronobulax.

You are welcome, although PeKaJe did all the work and this thread is littered with my concerns about/opposition to the idea. Good thing I don't always have to be Right :-)
 
You are welcome, although PeKaJe did all the work and this thread is littered with my concerns about/opposition to the idea. Good thing I don't always have to be Right :-)
Hey, investigating and testing a feature that you were originally skeptical about, finding that it works, and eventually accepting on that basis it is a mark of good software development, as far as I'm concerned.
 
Okay, I do have one incredibly minor request. Could we change the Daily Deed so its default selection reads "Deck of Every Card" rather than "- Draw a card -"? Most other Deeds are labeled with their source, so it'd just make it fit in better :D

[/obsessiveness]
 
I actually had that to begin with, but found that it pushed the card draw count out of view with the default settings on my Linux machine, so I went with something shorter. I don't mind either way, though. If it keeps bothering me, I can just change it to what I want with a small personal patch, like the number of other UI tweaks I've added over time.
 
Okay, I do have one incredibly minor request. Could we change the Daily Deed so its default selection reads "Deck of Every Card" rather than "- Draw a card -"? Most other Deeds are labeled with their source, so it'd just make it fit in better :D

[/obsessiveness]

Remind me. I'll try and free some cycles to try it.
 
One aspect that still appears to be missing, is utilizing the 'gift card'. The CLI doesn't automate through using the gift card.
 
Back
Top