24 Dec, 2011, Valo wrote in the 1st comment:
Votes: 0
I was just wondering if anyone has a customizable +census command that would work on MUX 2.9. Thanks in advance.
24 Dec, 2011, Idealiad wrote in the 2nd comment:
Votes: 0
I just looked in MUX core (on Google Code) and Faraday's repo (on Github) with no luck unfortunately. What do you want it to do? I'm sure we can work it out here. Alternatively, ask on WORA, there's way more mush coders there.
24 Dec, 2011, Valo wrote in the 3rd comment:
Votes: 0
I'm just trying to get something to search the approved players (signified by an approved attribute) for race and genders. I'd like to have it show how many people are of a certain race as well as how many are male and how many are female. I just want it to search the approved players. I'll check out WORA too. I appreciate it.
25 Dec, 2011, Idealiad wrote in the 4th comment:
Votes: 0
OK, first get your players:

@create census
&players census = search(type=player)


To filter for your approved players, you just change the search a bit:

&players census = search(etype=hasattr(##, approved))
The etypesearch class means 'get all players and evaluate this; if the evaluation is true, keep the player, if not, remove them. The '##' means the dbref of the player the search is looking at.

Next, for each player in this list, check their race and gender and increment a counter for each.

If I want to keep track of the categories race and gender, I'll declare that:

&categories census = race gender
I won't assume what's contained in the category attribute, but just count how many I find. I'll store these counters as attributes on the census object, making new attributes if they don't already exist, otherwise just adding to the existing attribute. I'll do this for each category:

&update census =
iter(
v(categories),
[setq(0, get(%0/itext())][ifelse(hasattr(me, [%q0]-count), set(me, [%q0]-count:[inc([%q0]-count))]), set(me, [%q0]-count:1))])


So update says, for each value in categories, set the q0register to what's in the attribute %0/value. Then check if %0/value is an attribute of the census (I add -count as a convenient way to distinguish the counters on the census object). If so, get its value and increase it by 1. If the attribute isn't there, create it and set it to 1. That's the counter.

What is %0? That's the dbref of the player we're looking at.

In other words, taking 'race' as the first value in categories, set the q0 register to what's in player/race. Say that's 'vampire'. If 'vampire-count' is an attribute on the census, get its value and increase it by 1. If it's not an attribute already, create it and set it to 1.

After it's done with the first item in categories, update will move on to the next, gender, and then it's done.

Now I want to run update for every approved player.

&run census = map(me/update, u(players))
Map runs update for every player in u(players). It sends that player as %0 to update.

To recap:

@create census
&players census = search(etype=hasattr(##, approved))
&categories census = race gender

&update census =
iter(
v(categories),
[setq(0, get(%0/itext())][ifelse(hasattr(me, [%q0]-count), set(me, [%q0]-count:[inc(v([%q0]-count))]), set(me, [%q0]-count:1))])

&run census = map(me/update, u(players))


Now all that's left to do is gather up <value>-count attributes and display them to the player. There's a few ways you could go with that. Display everything, or selectively based on the player or staff privileges. What are you going for?


edit to add: just occurred to me that you might want to record the count of male Xs and female Xs. If that's the case you can change update slightly to check for the gender of the current player, and then update the appropriate counter. Let me know if that doesn't make sense.
25 Dec, 2011, Valo wrote in the 5th comment:
Votes: 0
I first off, want to say thank you so much for your help and for explaining everything to me. I'm really learning a lot.

What I'm thinking of is when the +census command is sent, the player sees something like:

Male: # Female: #

Changeling: # Human: # Hunter: # Mage: #
Shifter: # Sin-Eater: # Vampire: #

Just spaced out to look nicer using the ljust() function and using # to display the number of approved players that matches the gender or race. Pretty much to give the players an idea of what has already been approved and where we're short on.
25 Dec, 2011, Idealiad wrote in the 6th comment:
Votes: 0
Noticed a bug in the code, it should be eplayerrather than etype.

On with the display then. First to review:

@create census
&players census = search(eplayer=hasattr(##, approved))
&categories census = race gender

&update census =
iter(
v(categories),
[setq(0, get(%0/itext())]
[ifelse(hasattr(me, [%q0]-count), set(me, [%q0]-count:[inc(v([%q0]-count))]), set(me, [%q0]-count:1))])

&run census = map(me/update, u(players))


First get the counter attributes:

&counters census = lattr(me/*-count)
I like putting this kind of stuff into columns. Assuming a 78 character wide screen, 3 columns of 26 characters is comfortable.

There's some formatting to do to get acceptable output, so I'll define that in a helper function.

&display census = lcstr(edit(%0,-COUNT, ))
That removes the -COUNT from the attribute name and converts the string to lowercase.

&format census =
columns(
iter(v(counters), [ljust([u(me/display, ##)]:, 21, . )][v(##)]),
26)


That says for each counter attribute, send it to the display function, left justify it in a width of 21 characters, fill the empty space with a '.', and then append the value of the attribute.

It gives output like this:

vampire:………….10   werewolf:…………12   ghost:……………4
mortal:…………..30 mage:…………….12 changeling:……….3
demon:……………5 kindred:………….2 rubber-ducky:……..45


All you really have left to do at this point is two things. First put the census into a command. Next add a little code to run the census every time you approve a new character.

You probably want to do one last thing too; after you approve a new character and before you run the new census, wipe all the old counter attributes. That's probably the simplest way to rebuild the census and accounts for any deleted characters and so on. You can do that with something like,

iter(lattr(me/*-count), set(me, ##:))

Of course you can do that at any time the census would change. It depends how up-to-date you want the census to be.
26 Dec, 2011, Valo wrote in the 7th comment:
Votes: 0
I think I could add that last bit of code to the approval command or even use a cronjob to run it regularly. What do you think would be the best way to have it added to a command and do you think it'd work if I added the last command to an attribute on the object, I could use a simple @trigger to run it?
26 Dec, 2011, Idealiad wrote in the 8th comment:
Votes: 0
I posted a thread at WORA and made some changes to the code, and put that last bit in the &run, which is a simple way to go.

http://wora.netlosers.com/index.php?topi...
0.0/8