Author Topic: Help filtering a mapping  (Read 2605 times)

Offline daelaskai

  • BFF
  • ***
  • Posts: 174
    • View Profile
Help filtering a mapping
« on: October 30, 2006, 08:25:37 AM »
Hello,



I am trying to filter out a mapping and only show a select portion depending on creator input.  This is the mapping that I have:



code:

Bits = ([
      1: ([
            "description":"description",
            "type":"bug",
            "who":"Amun-Ra",
            "completed":0,
           ]),
      2:([
            "description":"description",
            "type":"idea",
            "who":"John Doe",
            "completed":1162194417,
           ]),
])




What I am attempting to do is take the Bits and only display select ones.  For instance, if the creator wanted to see only bugs, in the example mapping, it would only show the first bit #1.  I would not like to limit it to the "type" but be able to display all completed Bits which would display Bit #2 only.  Any ideas?  Any help would be appreciated :)



Daelas/Amun-Ra

Offline detah

  • BFF
  • ***
  • Posts: 190
  • Ruler of 2D
    • View Profile
Help filtering a mapping
« Reply #1 on: October 30, 2006, 08:50:55 AM »
What you are showing is a mapping of a mapping. And the outter mapping only has 1 entry. You would probably be better served with an array of a mapping.



code:

Bits = ({
             ([
              "description":"description",
              "type":"bug",
              "who":"Amun-Ra",
              "completed":0,
             ]),
            ([
              "description":"description",
              "type":"idea",
              "who":"John Doe",
              "completed":1162194417,
             ]),
          })




Now to filter something like this, you can use a dual set of loops.



code:

int acount=sizeof(Bit);
  for(i=0; i<acount; ++i) {
    for(j=0; j<3; ++j) {
      write(Bits[type]);
    }
  }




For the write, you may want to create some kind of input_to there to tell it to write out the type or who element. depending on your syntax of your command. You can collect subsets of element data in this way above. I am not sure if there is an easier way, but this is how I would do it.

Offline cratylus

  • Your favorite and best
  • Administrator
  • ***
  • Posts: 1020
  • Cratylus@Dead Souls <ds> np
    • View Profile
    • About Cratylus
Help filtering a mapping
« Reply #2 on: October 30, 2006, 09:04:17 AM »
You'll want something like this. This will filter based on either key or val, doesn't matter which. You'll want to do some sscanf parsing of arguments for specifiv key or val selectors.  

I'm pretty sure this will update for you. If not, at least it should get you much closer.

code:
int DisplayThing(mixed thing){
    mapping TmpMap = ([]);
    if(!sizeof(Bits)) return 0;
    if(member_array(thing, keys(Bits[keys(Bits)[0]])) == -1){
        //the arg is a val not a key
        foreach(mixed elementkey, mixed elementval in Bits){
            foreach(mixed key in keys(elementval)){
                if(Bits[elementkey][key] == thing) TmpMap[elementkey] = elementval;
            }
        }
    }
    else {
        //the arg is a key
        foreach(mixed elementkey, mixed elementval in Bits){
            foreach(mixed key in keys(elementval)){
                if(key == thing) TmpMap[elementkey] = elementval;
            }
        }
    }
    return copy(TmpMap);
}


Offline daelaskai

  • BFF
  • ***
  • Posts: 174
    • View Profile
Help filtering a mapping
« Reply #3 on: October 30, 2006, 09:10:54 AM »
This is the actual code that I have right now:



code:

mapping GetBits() { return Bits; }

varargs static void List(string *args, int print) {
      mapping bits;
      mapping bit;
      string nom, tmp = "", tmp2 = implode(args, " ");
    int bit_id;

    nom = (string)this_player()->GetKeyName();
    bits = (mapping)GetBits();
    tmp+= sprintf( "%s\t%s\t\t%s\n", "#", "Type", "Who" );
    foreach(bit_id, bit in bits) {
        tmp += sprintf( "%i\t%s\t\t%s\n", bit_id, bit["type"], bit["who"] );
    }
    if( tmp == "" ) {
       message("system", "No bits to view.", this_player());
       return;
    }
    if( print ) {
    string file;
    rm(file = user_path((string)this_player()->GetKeyName()) + "bits");
    write_file(file, strip_colours(tmp));
    message("system", "Bits have been printed.", this_player());
       }
    else this_player()->eventPage(explode(tmp, "\n"), MSG_SYSTEM);
    return;
}

static string GetBitString(int id, mapping bits) {
  string tmp;

  tmp = "%^YELLOW%^Bit ID:%^RESET%^ " + id + "\n";
  tmp += "%^YELLOW%^Reported by:%^RESET%^ " +
  Bits[id]["who"] + "\n";
  tmp += "%^YELLOW%^Type:%^RESET%^ " + bits[id]["type"] + "\n";

     if( bits[id]["completed"] ) {
      tmp += "%^YELLOW%^Status: %^RESET%^";
        tmp += "completed " + ctime(bits[id]["completed"]) + "\n";
     tmp += "%^YELLOW%^Notes:%^RESET%^\n" + bits[id]["resolution"] + "\n";
    }
    else
    tmp += "%^YELLOW%^Status: WAITING%^RESET%^";
    tmp += "\n%^YELLOW%^Creator info:%^RESET%^\n" + bits[id]["data"] + "\n";
tmp += "\n%^YELLOW%^Bit info:%^RESET%^\n" + bits[id]["bit"] + "\n";
return tmp;
}




GetBits() just returns the Bits mapping that I first described.  This code is based off the bug system currently in DS  /daemon/bugs.c and /secure/cmds/players/bug.c.

Offline llyr

  • Pottymouth
  • *
  • Posts: 1
    • View Profile
Help filtering a mapping
« Reply #4 on: October 30, 2006, 09:12:51 AM »
code:

string searchkey = "type";
string searchval = "ideas";

mapping Bits = ([
  1 : ([ "desc" : "thedesc1", "type" : "bugs" ]),
  2 : ([ "desc" : "thedesc2", "type" : "ideas" ]),
  3 : ([ "desc" : "thedesc3", "type" : "ideas" ]) ]);

foreach(int key, mapping value in Bits) {
  if (value[searchkey] == searchval) {
    do_whatever_with_this_mapping( Bits[key] );
  }
}




Here's one way to do it. The foreach iterates over the mapping, and checks to see if the searchkey:searchvalue pair exists in the inner mapping. If it does, then do something with that inner mapping (Bits[key]). The searchkey and searchvalue are provided for demonstration -- they would be taken from your search command's input normally, of course.

Offline daelaskai

  • BFF
  • ***
  • Posts: 174
    • View Profile
Help filtering a mapping
« Reply #5 on: October 30, 2006, 10:41:58 AM »
Thanks for all the help.  I used Cratylus' example and it works great.  I did have to put a couple checks in because if I did not have an argument, it seemed to take away some of identical types.  If I had 2 bugs and one praise type, for instance, it only showed one of the 2 bugs and the praise.



For the finished segment, I now have this:



code:

       varargs static void List(string *args, int print, int all) {
      mapping bits;
      mapping bit;
      mapping sbits;
      string nom, tmp = "", tmp2 = "";
      int bit_id;
    if( args ) tmp2 = implode(args, " ");
      if( validate()) {
          nom = (string)this_player()->GetKeyName();
          bits = (mapping)GetBits();
          if( sizeof(args) ) sbits = (mapping)DisplayThing(tmp2);
          else sbits = bits;
          if( !all ) tmp+= sprintf( "%s\t%s\t\t%s\n", "#", "Type", "Who" );
          foreach(bit_id, bit in sbits) {
         if( all ) tmp += GetBitString(bit_id, bits) + "\n*****\n\n";
         else tmp += sprintf( "%i\t%s\t\t%s\n", bit_id, bit["type"], bit["who"] );
          }
          if( tmp == "" ) {
         message("system", "No bits to view.", this_player());
         return;
          }
          if( print ) {
         string file;

         rm(file = user_path((string)this_player()->GetKeyName()) + "bits");
         write_file(file, strip_colours(tmp));
         message("system", "Bits have been printed.", this_player());
          }
          else this_player()->eventPage(explode(tmp, "\n"), MSG_SYSTEM);
          return;
      }
       }

       static string GetBitString(int id, mapping bits) {
      string tmp;

      tmp = "%^YELLOW%^Bit ID:%^RESET%^ " + id + "\n";
      tmp += "%^YELLOW%^Reported by:%^RESET%^ " +
      Bits[id]["who"] + "\n";
      tmp += "%^YELLOW%^Type:%^RESET%^ " + bits[id]["type"] + "\n";

      if( bits[id]["completed"] ) {
          tmp += "%^YELLOW%^Status: %^RESET%^";
          tmp += "completed " + ctime(bits[id]["completed"]) + "\n";
          tmp += "%^YELLOW%^Notes:%^RESET%^\n" + bits[id]["resolution"] + "\n";
      }
      else
          tmp += "%^YELLOW%^Status: WAITING%^RESET%^";
      tmp += "\n%^YELLOW%^Creator info:%^RESET%^\n" + bits[id]["data"] + "\n";
      tmp += "\n%^YELLOW%^Bit info:%^RESET%^\n" + bits[id]["bit"] + "\n";
      return tmp;
       }

       int DisplayThing(mixed thing){
      mapping TmpMap = ([]);
      if(!sizeof(Bits)) return 0;
      if(member_array(thing, keys(Bits[keys(Bits)[0]])) == -1){
          //the arg is a val not a key
          foreach(mixed elementkey, mixed elementval in Bits){
         foreach(mixed key in keys(elementval)){
             if(Bits[elementkey][key] == thing) TmpMap[elementkey] = elementval;
         }
          }
      }
      else {
          //the arg is a key
          foreach(mixed elementkey, mixed elementval in Bits){
         foreach(mixed key in keys(elementval)){
             if(key == thing) TmpMap[elementkey] = elementval;
         }
          }
      }
      return copy(TmpMap);
       }




This is not the entire file.  It is only the segment that I was working with but it works :)



Daelas/Amun-Ra