King smiles and waves to everyone. He steps up to the front of the room. "Thank you all for coming out. This Talk Night is entitled, Anomaly Jobs for Coders. I'd like to introduce our speaker for tonight, Grey." Steps down and hands over the floor to Grey.
Grey waves.
Rob has arrived.
Grey takes a moment to clean on the +jobs system from last week, so we have a fresh canvas.
Rob sits next to Ana and Sally.
Sally grins.
Grey says, "So, everyone is here to learn the deep, dark secrets of Jobs 5.0?"
Death nodnods!
Rob grins and nods, "Jobs 5.0 is for MUX/TM3, eh?
Rob wishes it was for Penn.
Grey says, "Someone is porting it for Penn, actually."
Rob heard that.
Rob is glad to hear that.
Grey says, "As I understand it the port is all ready, except for the pie chart code for the reports."
Rob ohs and likes that, I use 3.x.
Grey says, "Tonight will be much more free flowing that last week, and we only have four topics:"
Grey says, "So, what are Summarries? Well, they are something which is setup bucket by bucket, and appears between the Job header and the Job Comments. Summaries are optional. You don't have to use them, or use them on all buckets."
Grey says, "Take a look at '+job 1' for an example of the TPS summary, which comes as part of the Jobs 5.0 install."
Grey says, "The Summary would be the Approved, Players, Schedule, Arc, Staff and Synopsis section."
Ana oohs. Very nice.
cairo oooooooOOooohs.
Ana says, "So summaries contain different info for each bucket type?"
cairo says, "Approved does not mean +job/approve, right?"
Grey says, "As the coder, you code the summary. :)"
Grey says, "No, cario."
Ana nods.
Grey says, "cairo, even."
cairo thinks she worded the question wrong 'cause isn't sure what your answer means.
Ana thinks the summary response was to me. ;)
Grey says, "No, Approved has nothing to do with '+job/approve'."
cairo says, "Okay, thank you. :)"
Grey says, "TPS == Tinyplots, so in this context it means the plot is approved to run."
Grey | exa #1433/summary
cairo says, "Where #1433 is the bucket."
Grey says, "That's the code to handle the summary, which is set on the TPS Bucket object. Its much like setting up data for a +who, or +finger. %0 is the dbref of the Job object, so get(%0/approved) gets the contents of the APPROVED attribute from the Job itself, if present."
&SUMMARY TPS=[rjust(ansi(hc,Approved:),10)] [ifelse(hasattrp(%0,APPROVED), get(%0/APPROVED),Unapproved)]%r[rjust(ansi(hc,Players:),10)] [ifelse(hasattrp (%0,PLAYERS),itemize(map(me/MAP_NAME,get(%0/PLAYERS),%b,|),|),Nobody)]%r [rjust(ansi(hc,Schedule:),10)] [ifelse(hasattrp(%0,SCHEDULE),get(%0/SCHEDULE), Unset)]%r[rjust(ansi(hc,Arc:),10)] [ifelse(hasattrp(%0,PLOT_ARC), get(%0/PLOT_ARC),Unset)]%r[rjust(ansi(hc,Staff:),10)] [ifelse( hasattrp(%0,WRITER),itemize(map(me/MAP_NAME,get(%0/WRITER),%b,|),|),Nobody)] %r[rjust(ansi(hc,Synopsis:),10)] [ifelse(hasattrp(%0,BRIEF),get(%0/BRIEF),Unset)] &MAP_NAME TPS=[name(*%0)] &ACCESS TPS=[u(%va/FN_STAFFALL,%#)] &ACCESS_PLAYERS TPS=[orflags(%0,WZ)] &PROCESS_PLAYERS TPS=[setq(3,PLAYERS)][setq(e,secure(%0))][ifelse(not(gt(strlen(trim(squish(iter (%qe,if(not(isdbref(pmatch(itext(0)))),[setr(p,itext(0))]))))),0)),[setq(9,iter (%qe,pmatch(itext(0))))][setq(8,get(%1/PLAYERS))][iter(%q9,ifelse(gt(member(%q8 ,##),0),setq(8,setdiff(%q8,##)),setq(8,setunion(%q8,##))))][setq(1,%q8)]1,0)] &ERROR_PLAYERS TPS=I don't recognize [ansi(h,%qp)] as a player. &ACCESS_SCHEDULE TPS=[orflags(%0,WZ)] &PROCESS_SCHEDULE TPS=[setq(3,SCHEDULE)][setq(1,strtrunc(%0,50))]1 &ERROR_SCHEDULE TPS=You must enter a valid date string. &ACCESS_ARC TPS=[orflags(%0,WZ)] &PROCESS_ARC TPS=[setq(3,PLOT_ARC)][setq(1,strtrunc(%0,50))] &ACCESS_STAFF TPS=[orflags(%0,WZ)] &PROCESS_STAFF TPS=[setq(3,WRITER)][ifelse(not(gt(strlen(trim(squish(iter(%0,if(not(isdbref(pm atch(itext(0)))),[setr(p,itext(0))]))))),0)),[setq(9,iter(%0,pmatch(itext(0)))) ][setq(8,get(%1/WRITER))][iter(%q9,ifelse(gt(member(%q8,##),0),setq(8,setdiff(% q8,##)),setq(8,setunion(%q8,##))))][setq(1,%q8)]1,0)] &ERROR_STAFF TPS=I don't recognize [ansi(h,%qp)] as a player. &ACCESS_SYNOPSIS TPS=[orflags(%0,WZ)] &PROCESS_SYNOPSIS TPS=[setq(3,BRIEF)][setq(1,%0)]1 &ACCESS_APPROVED TPS=[orflags(%0,W)] &PROCESS_APPROVED TPS=[setq(3,APPROVED)][setq(1,%0)]1 &HELP TPS=%r[space(5)]This bucket is for currently active plots that are running on the grid. Care should be taken to keep the headers of these jobs up-to-date, especially in terms of Progress settings and due dates. When the plot is completed, the job should be set complete and left open until follow-up requests are completed. %r%r[u(%va/FN_BREAK,ansi(hc,Settings for +job/sumset))]%r[ljust(ansi(h,PLAYERS),10)] Accepts <player> as a valid parameter.%r[ljust(ansi(h,SCHEDULE),10)] Describe when the plot is in effect.%r[ljust(ansi(h,ARC),10)] Describes the story arc associated to this plot.%r[ljust(ansi(h,STAFF),10)] Accepts <player> as a valid parameter.%r[ljust(ansi(h,SYNOPSIS),10)] A brief synopsis of the plot. %r[ljust(ansi(h,APPROVED),10)] Wiz-only, for approving plots. Accepts 'yes' or 'no'.
Rob says, "So 5.0 still uses objects, instead of ATTRs to store information? So, there is no way to look at an old job, unless we modify the code to send a completed job to a completed bucket, eh?"
Grey says, "I'm not sure if I follow the question. Each Job is its own object, and the various pieces of info are stored in atrributes on that Job. The Job is now parented to the bucket it belongs in."
Grey says, "A for completed jobs, they are posted (normally) to Myrddin's BBS. I say normally, cause this test install of +jobs we're using won't post, as I didn't setup a test install of the BBS code as well."
Grey says, "I'm not sure if that answers your question?"
Ana nods. So you have to either alter the finishing code to post all comments to the bb and archive that, or do what Rob said to be able to go back later and look at old jobs.
Rob nods, "Yes, I got that Grey. My question was, why does +jobs not store the information for a job in an attribute on one object, instead of several attributes on one object per job.
Rob nods to Ana and thinks that's it.
Grey answers Rob first.
Grey says, "Buffer size. An attribute can only contain a set amount of data. On MUX its 8k or 8000 characters and MUSH its 4000, so if we stored all the data for one Job in one attribute, that limits the total Job size (including who its assigned to, who opened it, etc) to 4000 or 8000 characters. By using separate objects , one for each job, and storing each 'comment' in on attribute, then the Job size is more or less unlimited. (lattr will probably break at about 700 or so entries, if my math is right). Each comment is still limited to 4000 or 8000 characters, but the Job can contain lots of data."
Rob nods.
Grey says, "Ana, the posting to the BBS will store the opening and closing comment. If you want a log of /all/ info from the Job, then you can use the logging system. It basically dumps a copy of the whole Job via @log when you /complete, /approve, /delete, /deny, etc."
Grey | +jhelp logging
Output from +jhelp/logging:
Job logging cannot occur unless the log already exists on the server. You
must have access to your shell account to create these files, and you must
know the <filename> of the bucket's log that you need to create. The
<filename> is located at:
game/logs/M-<filename>.log
To create the logs, you can use touch, for example:
> cd logs
> touch M-joblog.log
The default <filename> is 'reqlog' for the REQ bucket and 'joblog' for all
other buckets. You can change where the <filename> logs to, but keep in mind
that the system already takes into account 'game/logs/M-' and '.log'.
cairo says, "Nice."
Grey says, "That's the helpfile, but basically is works with the current setup, so you will still get the BBS post with info, but you also get a text log of jobs to refer to."
Ana nods. I modified my system to post all comments because we have it set up so it'll work with our email command and email the archived job info to a googlegroup that's easily searchable.
Grey says, "As note, changing the commands which complete the Jobs to post all comments to the BBS, runs into the buffer problem I spoke of."
Ana nods.
Grey says, "In short, if the total data in the job is greater than the buffer when using Myrddin's BBS, then anything over the buffer is simply dropped and you lose it. The logging, however, does not suffer from that problem. It uses @log with each comment, so if the data is in the Job it will get logged."
Grey says, "Does that cover all the questions about attributes and job object setup?"
Grey takes the silence as a no, and moves back to Summaries and their setup.
Grey says, "So, the code I showed you early is the code to display the summary. Now we look at the more interesting part, setting up the summary for setting of data."
Grey says, "Three attributes control setting each piece of data. The first two, ACCESS_<info> and PROCESS_<info> are required while the third, ERROR_<info> is optional."
Grey | exa #1433/*staff*
Grey says, "ACCESS_<INFO> is a lock. If it returns 1, then the person can set data. If it returns 0, they can't. Now on the TPS bucket, you can see ACCESS_STAFF is set to 1. So anyone who can use the Jobs system and access the TPS bucket can set the Staff data."
Grey says, "You could something like '&ACCESS_STAFF TPS=[hasflag(%0,WIZARD)]"
Grey says, "So, if the person is a wizard they can set the data and if not they can't. Pretty forward to all the coders here, I think."
Grey says, "The PROCESS_STAFF one is a little more complicated. First, you need to use setq(3 to set the name of the attribute you want the data stored in. [setq(3,WRITER)] indicates that the data will be stored on the Job itself (not the bucket, with the attribute WRITER."
Grey says, "setq(1 is the data to be stored."
Grey says, "Lastly PROCESS must return 1 or 0."
Grey says, "1 indicates that the data is valid and to store it, and 0 indicates its not. If there is no ERROR_STAFF, then it uses the default error. Since there is an ERROR_STAFF, it will display that error."
Output from +jhelp summary:
A Summary is a special type of sub-header that appears under the primary
header. It can be used to display arbitrary information about the job,
the poster, or types of jobs.
Take a look at the summary from the TPS bucket:
-----------------------------------------------------------------------------
Approved: Yes
Players: Laco, O'Rielly
Schedule: Feb 2, 2006
Arc: Groundhog Day
Staff: Starfleet
Synopsis: While celebrating Sid Vicious' birthday, Laco and O'Rielly are
thrown into a short-term temporal loop.
-----------------------------------------------------------------------------
This information is independent of the comments added to the job and can be
altered by the user using '+job/sumset'. If set on a bucket, it is local, and
if set on the parent, the behavior is global.
To set a summary:
&SUMMARY <Bucket>=<text>
It is passed two parameters:
%0 = Job DB#
%1 = Enactor's DB#.
See also: sumsetting
Output from +jhelp sumsetting:
Summary settings should only be set on the bucket, and not the parent. If
set on the parent, then it becomes a bucket setting and /sumset will not
function on it (though +bucket/set will pick it up, as both formats are
identical).
A summary setting requires two attributes and has an optional third:
ACCESS_<setting> (required)
PROCESS_<setting> (required)
ERROR_<setting>
If you need to see examples, refer to the TPS bucket's settings.
ACCESS_<setting>:
The ACCESS_<setting> determines who can use /sumset on the <setting>. It is
passed one argument: %0, which is the Player DB# being tested. It returns
1 if the player can access <setting> and 0 if not.
PROCESS_<setting>:
This is the most complicated attribute. It requires:
[setq(3,<attribute>)][setq(1,<data>)][<test input, return 1 or 0>]
Optional:
[setq(2,<error>)]
<attribute> is the attribute to set on the job object if the input is
accepted. <data> is the data that is getting set (null will clear the attr).
At the end of the two registers, you should test the input and return 1 if
the input was acceptible, and 0 if it was not.
Only if this returns 1 does <attribute> get set to <data>.
ERROR_<setting>
If PROCESS_<setting> has returned 0, then the code will generate an error
message.
If you set %q2 in PROCESS_<setting>, then error message attributes will be
constructed like so:
ERROR_<setting><%q2>
In this way, you can display 'complex' errors that make sense, such as the
classic: 'That is not a player.', 'That player is not approved.', and 'That
player is not of the Ninja class.'
Azazel has arrived.
Grey says, "So, let me show those in use."
Grey | +job/sumset 1/staff=king cairo grey
JOBS: Job 1's STAFF parameter updated by Grey.
Grey says, "That command breaks down like this: +job/sumset <job #>/<summary area>=<data>."
Grey says, "So, since I used 'staff' for the summary area, then +job/sumset code first looks to see if I pass that lock. I did."
cairo says, "Oh, very nice!"
Grey says, "It then checks to see if 'king cairo grey' are all valid players, and since we are PROCESS returns 1 and makes %q3 equal to WRITER and %q1 equal to the dbrefs of the three players listed."
Steven has arrived.
Grey says, "This way you can control the access to each section, you can check the data to make sure the staffer is entering the right kind of data, and you can provide a custom error message, if they did something incorrect."
King says, "So it only checks if they are valid players, not valid staffers?"
Grey says, "In this case, yes."
King nods. "Okay." :)
cairo says, "custom error message | idiot, type it right this time."
Rob nods.
Grey says, "But anyone can change the code to their needs. Since Anomaly, were Starfleet and I developed the code, does allow for guest writers and only staff have accees to TPS, we allow the Staff one to contain non-staffers."
Grey says, "The key is that you guys as the coders can create your own summaries to fit your own needs. That's why I'm not talking about the actual code in PROCESS_STAFF too much."
Grey says, "Everyone (aside from those who just arrived) understand and see how that system works?"
cairo says, "Yessir."
Death nods. "Yep. :)"
Ana nods.
Grey says, "You can also do 'exa #1447' to see how APPROVED, PLOT_ARC, PLAYERS, WRITER and BRIEF are stored on the job itself."
Rob nods.
Grey says, "We're created four summaries now. The TPS one, an XP bucket one, one for tracking non-plot projects and one for +reports (a separate Jobs install on Anomaly that the players use). The XP one lets us assign players to get extra XP (above normal votes). Its processed once a week. Each day via @daily the bucket is checked to see if its ovedue. If it is, the players get the XP, the old job dateleted and via a hook, a now job opened automatically."
Grey says, "So, you can really automate some stuff if you want. Let me grab the URL to where Fleety shared the XP bucket. We won't talk about it here, but you guys can look it over."
Grey | http://mushpark.com/pipermail/anomalyjobs/2006-February/000026.html
Grey says, "PS, you guys can all sign up to that mailing list to ask questions, report bugs and give suggestions."
Grey says, "Did anyone have questions about Summaries then? Or shall I move on?"
Death ooohs, "Very nice. :)"
King says, "Fleety be good!"
cairo says, "Moving on is fine but then I'm no coder."
Death is fine with moving on.
Rob says, "Oh sure, Death is fine with death too, but I ain't! jk."
Death cackles.
Steven has disconnected.
Ana is good.
Grey says, "So, then, skins."
Grey says, "Let me intro skins for a moment for those not there last week. Do a '+jobs'."
Grey says, "Unless you were here last week and still have your skin set, you're looking at the DEFAULT skin."
Grey says, "Now do '&jobskin me=chrome' and then '+jobs' again."
Death says, "Oh wow.. nice!"
Ana oohs.
Grey says, "Jobs 5 comes with the the DEFAULT and CHROME skins. You, however, can edit those or add more."
cairo looks at Death and *grins*.
Rob eeps at the bright, but yeah.
Grey says, "While a little spammy, take a look at 'exa #1416/DEFAULT*'"
Output from exa #1416/DEFAULT*: &DEFAULT_READ Job Database <JD>=[repeat(-,79)]%r[ifelse(u(%va/EDIT_ACCESS,%#),[ansi(h,%[)][ifelse(and(or(u (%va/IS_PUBLISHED,%1),switch(extract(get(%1/%0),3,1,|),u(%1/OPENED_BY),1,0),has flag(%1/%0,no_inherit)),u(%va/IS_PUBLIC,%1)),ansi(hc,[rest(%0,_)]+),ansi(hc,[re st(%0,_)]-))][ansi(h,%])]%b,)][ansi(h,[extract(get(%1/%0),4,1,|)] added on [convsecs(extract(get(%1/%0),2,1,|))]:%b )][edit(last(get(%1/%0),|),@@PIPE@@,|)] &DEFAULT_HEADER Job Database <JD>=[switch(%0,,[repeat(=,79)],[center(| [ansi(hy,%0)] |,79,=)])] &DEFAULT_FLAGS Job Database <JD>=[ifelse(u(me/IS_LOCKED,%0),u(me/FN_FLAG,LOCKED,hr),)][ifelse(u(me/IS_PUBLI C,%0),u(me/FN_FLAG,Myjobs),)][ifelse(u(me/IS_PUBLISHED,%0),u(me/FN_FLAG,Publish ed),)][ifelse(u(me/IS_TAGGED,%0),u(me/FN_FLAG,Tags),)] &DEFAULT_FOOTER Job Database <JD>=[switch(%0,,repeat(=,79),center(| %0 |,79,=))] &DEFAULT_BANNER Job Database <JD>=[setq(0,%0)][setq(x,itemize(map(MAP_NAME,get(%q0/OPENED_BY),%b,|),|))][lju st([rjust(ansi(hc,Bucket:),10)] [u(%va/FN_BUCKETNAME,%q0)],40)][rjust(ansi(hc,Due On:),12)] [ifelse(get(%q0/DUE_ON),ifelse(gt(secs(),get(%q0/DUE_ON)),OVERDUE!,convsecs(get (%q0/DUE_ON))),-)]%r[ljust([rjust(ansi(hc,Title:),10)] [get(%q0/TITLE)],40)][rjust(ansi(hc,Status:),12)] [switch(get(%q0/PRIORITY),1,Green,2,Yellow,3,Red)] %([switch(get(%q0/STATUS),0,On Hold,1,New,2,Underway,3,25%%,4,50%%,5,75%%,6,100%%,?)]%)%r[ljust([rjust(ansi(hc ,Opened On:),10)] [convsecs(get(%q0/OPENED_ON))],40)][rjust(ansi(hc,Assigned To:),12)] [ifelse(isdbref(get(%q0/ASSIGNED_TO)),name(get(%q0/ASSIGNED_TO)),Nobody)]%r[rju st(ansi(hc,Opened By:),10)] %qx &DEFAULT_BREAK Job Database <JD>=switch(%0,,repeat(-,79),rjust(%[%0%],79,-)) &DEFAULT_JOBSHEADER Job Database <JD>=localize([u(FN_HEADER,Anomaly Jobs [u(VERSION)])]%r[setq(1,[secure(switch(hasattrp(%0,JOBS),1,lcstr(mid(get(%0/JOB S),0,20)),u(JOBS_DEFAULT)))])][ansi(hc,*%b%b[ljust(Job#,5)][iter(lnum(strlen(%q 1)),u(HEADER_[mid(%q1,##,1)]))])]%r[u(FN_BREAK)]) &DEFAULT_JOBLIST Job Database <JD>=[setq(0,secure(ifelse(hasattrp(%1,JOBS),lcstr(mid(get(%1/JOBS),0,20)),get( %va/JOBS_DEFAULT))))][setq(1,ifelse(get(%0/DUE_ON),ifelse(gt(secs(),get(%0/DUE_ ON)),r,switch(get(%0/PRIORITY),1,g,2,y,3,r,g)),switch(get(%0/PRIORITY),1,g,2,y, 3,r)))][ifelse(u(%va/FN_ISNEW,%0,%1),[ansi(hr,*)]%b,%b%b)][ansi(h%q1,[rjust([la st(name(%0))],5)]%b[iter(lnum(strlen(%q0)),[u(%va/DISPLAY_[mid(%q0,##,1)],%0,%1 )])])] &DEFAULT_SUMMARY Job Database <JD>=%r[repeat(-,79)]%r[u(parent(%0)/SUMMARY,%0)] &DEFAULT_STAFFSUM Job Database <JD>=[localize(%r[repeat(-,79)]%r[rjust(ansi(hc,DB#:),10)] %0[space(10)][rjust(ansi(hc,Comments:),10)] [setr(z,words(lattr(%0/COMMENT_*)))]%r%r[rjust(ansi(hc,Players:),10)] %(Players contributing to this job%)%r[setq(y,setunion(iter(lattr(%0/COMMENT_*),extract(get(%0/##),4,1,|),%b,| ),,|))][columns(%qy,20,|,11)][ifelse(hasattr(%0,LIST_READERS),%r[rjust(ansi(hc, Readers:),10)] %(Players who have read this job in the past%)%r[setq(z,iter(get(%0/LIST_READERS),first(##,|)))][columns(map(%va/MAP_NA ME,%qz,%b,|),20,|,11)],)][ifelse(hasattr(%0,TAGGED_FOR),%r[rjust(ansi(hc,Tags:) ,10)] %(Players this job has been tagged for%)%r[columns(map(%va/MAP_NAME,get(%0/TAGGED_FOR),%b,|),20,|,11)],)]%r[rjust( ansi(hc,Stats:),10)]%r[columns(iter(ifelse(hasattr(%0,LIST_STATS),sort(get(%0/L IST_STATS)),),[first(##,|)] [last(##,|)],%b,|),20,|,11)]%r)] &DEFAULT_BUCKETLIST Job Database <JD>=[ifelse(u(%va/FN_WIZONLY,%#),[ljust(name(%0),6)]%b%b[ifelse(u(%va/FN_MONIT ORCHECK,%0,%#),V,-)][ifelse(u(%va/IS_HIDDEN,%0),H,-)][ifelse(u(%va/IS_LOCKED,%0 ),L,-)][ifelse(u(%va/IS_TAGGED,%0),T,-)][ifelse(u(%va/IS_PUBLIC,%0),M,-)][ifels e(u(%va/IS_PUBLISHED,%0),P,-)][ifelse(u(%va/IS_SUMMARY,%0),S,-)]%b%b[strtrunc(l just(get(%0/DESC),40),30)][rjust(words(children(%0)),5)][rjust(mul(round(fdiv(w ords(children(%0)),words(lcon(%va))),2),100)%%,5)]%b%b[rjust(get(%0/POST_COMPLE TE),2)]%b[rjust(get(%0/POST_APPROVE),2)]%b[rjust(get(%0/POST_DENY),2)][rjust(de fault(%0/TURNAROUND,0),5)][rjust([ifelse(hasattr(%0,STAT_ART),[div(fdiv(first(g et(%0/STAT_ART)),rest(get(%0/STAT_ART))),86400)]d,-)],7)],[ljust(name(%0),6)]%b %b[strtrunc(ljust(get(%0/DESC),50),50)]%b[rjust(ifelse(u(%va/FN_MONITORCHECK,%0 ,%#),Yes,-),20)])] &DEFAULT_BUCKETHEADER Job Database <JD>=[u(FN_HEADER,Bucket List)]%r[ifelse(u(%va/FN_WIZONLY,%#),[ansi(hc,[ljust(Name,9)][ljust(Flags,6)]%b %b[ljust(Description,30)][rjust(#Jobs,5)][rjust(Pct,5)][space(3)]C%b%bA%b%bD%b% bDue[space(3)]ARTS)],[ansi(hc,[ljust(NAME,8)][ljust(Description,50)]%b[rjust(Vi ewing,20)])])]%r[u(FN_BREAK)]
Grey says, "Now I will mention one next thing about skins. If I wanted to /just/ change how the header and footer look for a custom skin, I can create a GREYS_HEADER and GREYS_FOOTER and set GREYS_SKIN to 1. For the other skin items which I didn't create, like say DEFAULT_READ, the system will just use the DEFAULT skin items."
Grey says, "So, now, we can all blend +jobs into our current 'look' for softcoded globals."
King says, "Or the feel of your particular game..."
Grey says, "Yes, the look. ;P"
King laughs and nods.
Grey says, "Any questions about skins? Obviously the concept is simple, just requires a fair bit of coding/tweaking to take advantage of it."
Death says, "Seems pretty straight forward to me."
cairo says, "Yeah, how did you get orange on the anomaly jobs skin? :)"
Grey says, "Which orange? Which part of the skin?"
cairo says, "Um, the top bar."
King says, "I shared the link you posted for the +reports screen shot..."
cairo says, "I'm not sure ... yeah."
Grey says, "Oh, the +reports skin. That's our little LCARS skin. That should be just yellow, no highlight."
Grey | think ansi(y,test)
cairo says, "Huh, looks different there, but must just be color oddities."
Grey says, "That's the color, yeah. Or there is the legend bar, which is yellow background."
Grey | think ansi(Yx,Test)
Azazel has disconnected.
Grey says, "So, moving on to Hooks. Who here played with the old TRIG_APP hook from older Jobs versions?"
Ana has a little.
Grey says, "Well, Starfleet expanded on the whole concept of Hooks. Now you can have a hook for virtually anything."
Grey says, "So let's say you want something to happen when a new CODE job is /create'd. You can put a HOOK_CRE on the CODE bucket object, and whatever is in that hook will be executed each time a new CODE job is created."
Grey says, "I'm actually going to use the XP bucket I gave the link to earlier to show off some Hooks."
Grey | &HOOK_DEL XP=@fo [owner(me)]={+job/create [name(me)]/XP Tracking=%%r%%r+job/sumset <job#>/PLAYERS=<player>: Add a player to this automated XP Job.%%r%%rThis job will automatically process itself some time after it goes overdue. To trigger the update manually%, you can /delete the job.};@dolist [u(%0/PLAYERS)]=@fo [owner(me)]=+xp/adj [name(##)]=1
Grey says, "So with this set on the XP bucket, when you +job/delete the current job, HOOK_DEL is executed and automatically creates a new job."
Grey says, "You can set a hook for each of the actions hooks, like ADD, APR, CRE, DEL, DNY, etc."
Grey says, "'+jhelp hooks' has the details, rather than me repeating them."
Grey says, "Any questions about hooks?"
Output from +jhelp hooks:
Action Hooks
All actions have what are called action hooks, which are arbitrary commands
that you can add to buckets to make the jobs process more automated and
extensively expand the capabilities of the system. This is where the real
power of Anomaly Jobs is located.
These can be set either on the bucket or the bucket parent. If set on the
bucket, an action hook will be for that local bucket only. If set on the
parent, an action hook will be for all buckets. Setting them on a job is
silly, but possible (the hook will be destroyed when the job is, and won't
have any powers while it is there).
The HOOK_<action> is passed three parameters:
%0: Job DB#
%1: DB# of actions enactor.
%2: DB# of the bucket.
&HOOK_CRE <Job Parent Object>=&ASSIGNED_TO %0=%1
In the above example, the job is assigned to the creator. Since this is
set on the parent, this behavior is global.
&HOOK_APR <Job Parent Object>=@trigger [v(VA)]/TRIG_LOG=%0,[v(VA)]
In the above example, the job will log to the server logfile when it is
+job/approved. Since it is set on the parent, it is global behavior.
&HOOK_ADD <REQ bucket>=@pemit/list [u(%0/OPENED_BY)]=JOBS: Comments
added to [name(%0)] by [name(%1)];@set %0/[dec(get(%0/NUM_COMMENT))]=
no_inherit
In the above example, whenever anyone /adds to a job in the REQ bucket,
the player who opened it is sent a broadcast message, and then the
comment is published (no_inherit set on a COMMENT_* determines if it is
published or not).
Death shakes his head.
Ana is good so far. :)
cairo has none.
Grey says, "You guys are making this nice and easy. I like it. :)"
Grey says, "So the last is Letters."
Grey says, "Letters let you control what is posted to the BBS or mailed to the player, or controlling what an added comment looks like."
Grey says, "So if I put a PLETTER_APR on the Code bucket, then when a CODE job is +job/approve'd, the code I put in the PLETTER_APR is used."
Grey says, "If I using a Summary with some data in it, I could use the PLETTER_APR to grab that data and add it to the post, as one example of how this could be used."
Grey says, "'+jhelp letters' contains all the important details about configuring them."
Death likes. :D
Grey says, "One note about both Letters and Hooks -- normally you set them on the Bucket, but there is now a Job Parent Object which all buckets are parented to. If you set the letter or hook on that, then the letter and hook apply to all buckets."
karin has arrived.
Grey says, "Any questions about letters?"
cairo has no questions.
Anomaly Jobs supports three types of form letters:
Topic Description Updated
----------------------------------------------------------------------------
aletter Addition letters - formatting an added comment. 06Jan30
pletter Post letters - posting a letter to the BBS. 06Jan30
mletter Mail letters - sent to the OPENED_BY list. 06Jan30
An ALETTER is a form letter for formatting/hardwiring job comment additions.
If it exists on the parent or bucket, the contents of it are posted to the
job, overriding any previous text it was supposed to write. It is formatted
in the following fashion:
&ALETTER_<action> <bucket/parent>=<text>
It is passed three arguments:
%0 = Job DB#
%1 = Creator DB#
%2 = Original text to post.
Examples:
&ALETTER_ADD <parent>=%r%2
&ALETTER_OTH <apps bucket>=[name(%1)] has submitted an application for a
[race(%1)] [class(%1)] with the following comments: %2
In the first example, a carriage return is added before all comments when
the +job/add command is used anywhere in the system. In the second example,
a job in the APPS bucket displays some basic character information on the
applicant before showing his comments on the app.
A PLETTER is a form letter that is posted to the BBS. If it exists on the
parent or bucket, then a letter will be generated when the action code is
triggered. It is formatted in the following fashion:
&PLETTER_<action> <bucket/parent>=<text>
The destination BBS is determined by the bucket. If the action is a DNY, it
will post to the POST_DENY board. If it is a COM, the system will post to the
POST_COMPLETE board. If the action code is any other code, it will post to
the POST_APPROVE board.
It is passed four arguments:
%0 = Job DB#
%1 = Action Code
%2 = Player DB#
%3 = Original Text
Examples:
&PLETTER_DEL <parent>=[name(%2)] has deleted [name(%0)].
&PLETTER_APR <Apps bucket>=[name(%2)] has approved [name(get(%0/
OPENED_BY))] for roleplay on [time()].
In the first example, when a job is deleted, a post is made to the board
noting it. In the second example, when an APPS job is /approved, the board
is posted with a notification that someone has approved the player.
An MLETTER is a form letter that is mailed to the player if it exists either
on the bucket or the parent. It is formatted in the following fashion:
&MLETTER_<action code> <bucket/parent>=<text>
An MLETTER is only mailed to the people in the OPENED_BY list set on the
job. If you need to mail arbitrary players, you should use a HOOK_* and
manually fire off the Job Tracker's TRIG_MAIL trigger.
MLETTER is passed four arguments:
%0 = Job DB#
%1 = Action Code
%2 = Player DB#
%3 = Original Text
Example:
&MLETTER_PUB <Query bucket>=[name(%2)] has released new comments in
[name(%0)]. Please type '+myjob [last(name(%0))]' to view these
comments.
In the above example, the people in the job's OPENED_BY attribute are sent
an @mail letting them know that comments have been published to their QUERY
job.
Grey says, "Okay, aside from the 'where to get Jobs 5.0' question, any questions at all?"
Rob wonders if you have a guesstimate on the Penn version release?
King shakes his head.
Grey was just about to page you Rob. :)
Grey says, "The guy working on the Penn port is on the mailing list, so if you sign up and and toss out an email to the list, he can let you knw."
Death likes, lots.
Grey answers here though, since you asked here.
King hehs.
Grey says, "A big part of the Jobs 5 release is about making the back end more useful for coders, so you guys can extend the ability and functionality of Jobs in whatever way you need."
Grey says, "And the nice part of Summaries, Skins, Letters and Hooks is that, unlike modifying the actual commands, is that when there is a new release of the code you don't lose your changes."
Ana says, "Definitely good. :)"
King nods. "Having used summaries already, I can say...they are a big help!"
Grey says, "For those who missed it, the mailing list is at: http://mushpark.com/mailman/listinfo/anomalyjobs"
Grey says, "And code? Its at: http://anomaly.mushpark.com/transfer.html"
Grey says, "So no more questions then?"
cairo has none. :)
Death shakes his head. "Good presentation. :)"
King has disconnected.
karin goes home.
karin has left.
cairo says, "Yes, thank you for that."
cairo is impressed with how understandable this was even to me.
karin has arrived.
Rob chuckles.
Grey says, "No problem. I do suggest you guys feel free to sign up to mailing and ask any questions you might have."
Ana says, "Thanks. :)"
Grey says, "But otherwise, with no questions, we're done here tonight. Thanks for coming out."
Death claps. :)
cairo says, "That is so wrong. Death claps."
Death beams.
Ana has disconnected.
cairo just shakes her head. :)
cairo has left.
karin wants to get back to the park.
Sally returns to the Forum.
Sally has left.
karin has left.
Death has left.