Made setAssessorPool use mew address if there aren't enough users

import "lib/random.sol";
import "userMaster.sol";
import "assessment.sol";
import "user.sol";
import "tagMaster.sol";

/*
@type: contract
@name: Tag
@purpose: To store tag data and create and store information about assessments of this tag
*/
contract Tag
{
  address[] parentTags; //The tags that this tag is child to (ie: Calculus is child to Math)
  address[] childTags; //The tags that this tag is parent to (ie: Math is parent to Calculus)
  address userMaster; //The address of the userMaster contract
  address tagMaster; //The address of the tagMaster contract
  address random; //The address of the random contract
  string name; //The name of the tag
  int maxScore = 0; //The highest score acheived for this tag
  uint maxSize = 5; //The largest assessment taken for this tag
  address[] owners; //Those who have earned the tag
  address mew;
  mapping (address => address[]) assessmentHistory; //All assessments completed
  mapping (address => int) currentScores; //The most recent score of a user
  mapping (address => uint) assessmentSizes; //The most recent size of an assessment taken by a user
  mapping(address => bool) assessmentExists; //All existing assessments

  /*
  @type: modifier
  @name: onlyUserMaster
  @purpose: to only allow the UserMaster contract to call a function to which this modifier is applied
  */
  modifier onlyUserMaster
  {
    if(msg.sender != userMaster) //checks if msg.sender has the same address as userMaster
    {
      throw; //throws the function call if not
    }
  }

  /*
  @type: modifier
  @name: onlyTagMaster
  @purpose: to only allow the TagMaster contract to call a function to which this modifier is applied
  */
  modifier onlyTagMaster
  {
    if(msg.sender != tagMaster) //checks if msg.sender has the same address as tagMaster
    {
      throw; //throws the function call if not
    }
  }

  /*
  @type: modifier
  @name: onlyThis
  @purpose: to only allow the this contract to call a function to which this modifier is applied
  */
  modifier onlyThis
  {
    if(msg.sender != address(this)) //Checks if msg.sender is this contract
    {
      throw; //Throws out the function call if it isn't
    }
  }

  /*
  @type: event
  @name: CompletedAssessment
  @purpose: To build a database of completed assessments
  */
  event CompletedAssessment
  ( address _assessee, //The address of the user who took the assessment
    bool _pass, //Whether or not the assessee passed the assessment
    int _score, //The score of the assessee
    address _assessment); //The address of the assessment

  /*
  @type: constructor function
  @purpose: To initialize the Tag contract
  @param: string tagName = the name of the tagName
  @param: address[] parents = the addresses of the tag's parents
  @param: address userMasterAddress = the address of the UserMaster contract
  @param: address tagMasterAddress = the address of the TagMaster that spawned this user
  @param: address randomAddress = the address of the ransom contract
  @returns: nothing
  */
  function Tag(string tagName, address[] parents, address userMasterAddress, address tagMasterAddress, address randomAddress)
  {
    name = tagName; //sets to value of name to that of tagName
    parentTags = parents; //sets the value of parentTags to that of parents
    userMaster = userMasterAddress; //sets the value of userMaster to that of userMasterAddress
    random = randomAddress; //sets the value of random to that of randomAddress
    tagMaster = tagMasterAddress; //sets the vale of tagMaster to that of tagMasterAddress
  }

  /*
  @type: function
  @purpose: To set the first user for this tag
  @param: address firstUser = the address of the first user to own the tag
  @returns: nothing
  */
  function addUser(address user) onlyUserMaster
  {
    if(address(this) == mew)
    {
      owners.push(user); //If there aren't then firstUser is made to be an owner of this tag
    }
  }

  function setMew(address mewAddress) onlyTagMaster
  {
    mew = mewAddress;
  }

  /*
  @type: function
  @purpose: To get the most recent score of a user
  @param: address user = the user whose score is to be checked
  @returns: The user's most recent score in the form of an int
  */
  function getCurrentScore(address user) constant returns(int)
  {
    return currentScores[user];
  }

  /*
  @type: function
  @purpose: To get the size of the most recent asssessment of a user
  @param: address user = the user whose assessment size is to be checked
  @returns: The user's most recent assessment size in the form of an uint
  */
  function getAssessmentSize(address user) constant returns(uint)
  {
    return assessmentSizes[user];
  }

  /*
  @type: function
  @purpose: To get the owners of this tag
  @returns: The users that own this tag in the form of an array of addresses
  */
  function getOwners() constant returns(address[])
  {
    return owners;
  }

  /*
  @type: function
  @purpose: To get the number of owners of this tag
  @returns: The number of users that own this tag in the form of an uint
  */
  function getOwnerLength() constant returns(uint)
  {
    return owners.length;
  }

  /*
  @type: function
  @purpose: To get a specific owner of this tag
  @param: uint index = the index of the user in the owners array
  @returns: The user that owns this tag with that index in the form of an address
  */
  function getOwner(uint index) constant returns(address)
  {
    return owners[index];
  }

  /*
  @type: function
  @purpose: To get the parents of this tag
  @returns: The parents of this tag in the form of an array of addresses
  */
  function getParents() constant returns(address[])
  {
    return parentTags;
  }

  /*
  @type: function
  @purpose: To get the number of parents for this tag
  @returns: The number of parents for this tag in the form of an uint
  */
  function getParentsLength() constant returns(uint)
  {
    return parentTags.length;
  }

  /*
  @type: function
  @purpose: To get a specific parent of this tag
  @param: uint index = the index of the tag in the parentTags array
  @returns: The tag that is parent to this tag with that index in the form of an address
  */
  function getParent(uint index) constant returns(address)
  {
    return parentTags[index];
  }

  /*
  @type: function
  @purpose: To add a parent to the tag
  @param: address parentAddress = the address of the new parent tag
  @returns: nothing
  */
  function addParent(address parentAddress) onlyTagMaster
  {
    parentTags.push(parentAddress);
  }

  /*
  @type: function
  @purpose: To get the children of this tag
  @returns: The children of this tag in the form of an array of addresses
  */
  function getChildren() constant returns(address[])
  {
    return childTags;
  }

  /*
  @type: function
  @purpose: To get the number of children of this tag
  @returns: The number of children of this tag in the form of an uint
  */
  function getChildrenLength() constant returns(uint)
  {
    return childTags.length;
  }

  /*
  @type: function
  @purpose: To get a specific child of this tag
  @param: uint index = the index of the tag in the childTags array
  @returns: The tag that is child to this tag with that index in the form of an address
  */
  function getChild(uint index) constant returns(address)
  {
    return childTags[index];
  }

  /*
  @type: function
  @purpose: To add a child to the tag
  @param: address childAddress = the address of the new child tag
  @returns: nothing
  */
  function addChild(address childAddress) onlyTagMaster
  {
    childTags.push(childAddress);
  }

  /*
  @type: function
  @purpose: To get the name of this tag
  @returns: The name of the tag in the form of a string
  */
  function getName() returns(string)
  {
    return name;
  }

  /*
  @type: function
  @purpose: To recursively set the pool to draw assessors from in the assessment
  @param: address tagAddress = the tag that assessors are currently being drawn from
  @param: address assessment = the address of the assessment that assessors are being drawn for
  @param: uint seed = the seed number for random number generation
  @param: uint size = the desired size of the assessment
  @returns: nothing
  */
  function setAssessorPool(address tagAddress, address assessment, uint seed, uint size) onlyThis
  {
    if(Tag(mew).getOwnerLength() < Assessment(assessment).getAssessmentPoolSize()) //Checks if the requested pool size is greater than the number of users in the system
    {
      for(uint i = 0; i < Tag(mew).getOwnerLength(); i++) //If so, all users in the system are added to the pool
      {
        Assessment(assessment).addToAssessorPool(Tag(mew).getOwner(i));
      }
      Assessment(assessment).setAssessmentPoolSize(0); //Sets the remaining amount of user's desired in the pool to 0
      Assessment(assessment).setPotentialAssessor(size); //Has the assessment select random potential assessors (the amount is dictated by the size variable)
    }
    for(uint j = 0; j < Tag(tagAddress).getOwnerLength() && Assessment(assessment).getAssessmentPoolSize() > 0; j++) //Iterates through all the owners of the tag corresponding to tag address while the remaining amount of user's desired in the pool is greater than 0
    {
      uint numberSet = 0; //initializes a variable to keep track of how many assessors this tag has added to the pool
      if(numberSet < Tag(tagAddress).getOwnerLength()/10) //Checks if the number of assessors provided by this tag is less than 10% of the owners of the tag
      {
        address randomUser = Tag(tagAddress).getOwner(Random(random).getRandom(seed + j, Tag(tagAddress).getOwnerLength()-1)); //gets a random owner of the tag
        if(UserMaster(userMaster).getAvailability(randomUser) == true && (uint(Tag(tagAddress).getCurrentScore(randomUser))*Tag(tagAddress).getAssessmentSize(randomUser)) > (now%(uint(maxScore)*maxSize))) //Checks if the randomly drawn is available and then puts it through a random check that it has a higher chance of passing if it has had a higher score and a larger assessment
        {
          Assessment(assessment).addToAssessorPool(randomUser); //adds the randomly selected user to the assessor pool
          Assessment(assessment).setAssessmentPoolSize(Assessment(assessment).getAssessmentPoolSize() -1); //reduces desired amount of users to be added to the assessor bool by 1
          numberSet++; //increases numberSet by 1
        }
      }
      else
      {
        break; //exits this for loop if 10% or more of the tag owners are in the assessment pool
      }
    }
    if(Assessment(assessment).getAssessmentPoolSize() <= 0) //Checks if the number of desired users remaining for the assessment pool is no greater than 0
    {
      Assessment(assessment).setPotentialAssessor(size); //If so, the assessment selects random potential assessors (the amount is dictated by the size variable)
    }
    else //If not
    {
      for(uint l = 0; l < Tag(tagAddress).getParentsLength() || l < Tag(tagAddress).getChildrenLength(); l++) //Recursively calls this function in such a way that the parent and child tags' owners will be used to potentially populate the assessment pool
      {
        if(l < Tag(tagAddress).getParentsLength()) //Makes sure there are still parent tags left to call
        {
          setAssessorPool(Tag(tagAddress).getParent(l), assessment, Random(random).getRandom(seed + l, Tag(tagAddress).getOwnerLength()-1), size);
        }
        if(l < Tag(tagAddress).getChildrenLength()) //Makes sure there are still child tags left to call
        {
          setAssessorPool(Tag(tagAddress).getChild(l), assessment, Random(random).getRandom(seed + l, Tag(tagAddress).getOwnerLength()-1), size);
        }
      }
    }
  }

  /*
  @type: function
  @purpose: To make a new assessment
  @param: address assessee = the address of the assessee
  @param: uint time = the time that assessors will have to assess in this assessment
  @param: uint size = the size of the assessment
  @returns: nothing
  */
  function makeAssessment(address assessee, uint time, uint size)
  {
    if(size >= 5) //Checks if the assessment has a size of at least 5
    {
      Assessment newAssessment = new Assessment(assessee, address(this), userMaster, tagMaster, random, time); //Makes a new assessment with the given parameters
      assessmentExists[address(newAssessment)] = true; //Sets the assessment's existance to true
      newAssessment.setNumberOfAssessors(size); //Sets the number of assessors wanted in the assessment to equal size
      newAssessment.setAssessmentPoolSize(size*20); //Sets the number of users wanted to form the assessor pool to 20 times size
    }
    else
    {
      throw; //Throws out the function call if the size of the assessment is less than 5
    }
  }

  /*
  @type: function
  @purpose: To start the assessment process
  @param: address assessment = the address of the assessment
  @returns: nothing
  */
  function startAssessment(address assessment)
  {
    if(block.number - Assessment(assessment).getReferenceBlock() >= 4 && block.number - Assessment(assessment).getReferenceBlock() <= 6) //Checks if this function is being called 4 to 6 blocks after the block in which the assessment was created
    {
      setAssessorPool(address(this), assessment, Assessment(assessment).getNumberOfAssessors(), Assessment(assessment).getNumberOfAssessors()); //Calls thge function to set the assessor pool
    }
    else
    {
      Assessment(assessment).cancelAssessment(); //If this function is called too early or too late the assessment is cancelled
    }
  }

  /*
  @type: function
  @purpose: To finish the assessment process
  @param: bool pass = whether or not the assessee passed the assessment
  @param: int score = the assessee's score
  @param: address assessee = the address of the assessee
  @param: address assessment = the address of the assessment
  @returns: nothing
  */
  function finishAssessment(bool pass, int score, address assessee, address assessment)
  {
    if(msg.sender == assessment) //Checks to make sure this function is being callled by the assessment
    {
      if(pass == true) //If the assessee passed
      {
        owners.push(assessee); //Makes the assessee an owner of this tag
        UserMaster(userMaster).mapAchievement(assessee,address(this)); //Maps the assessee to this tag in the user master as one of the assessee's achievments
      }
      assessmentHistory[assessee].push(assessment); //Adds the assessment to the assessment history array
      currentScores[assessee] = score; //Maps the assessee to their score
      assessmentSizes[assessee] = Assessment(assessment).getNumberOfAssessors(); //Maps the assessee to the assessment size
      if(score > maxScore)
      {
        maxScore = score; //If this assessment's score is higher that the current highest score than the maxScore variable is updated with this score
      }
      if(Assessment(assessment).getNumberOfAssessors() > maxSize)
      {
        maxSize = Assessment(assessment).getNumberOfAssessors(); //If this assessment's size is larger that the current largest assessment size than the maxSize variable is updated with this size
      }
      CompletedAssessment(assessee, pass, score, assessment); //Makes an event with this assessment's data
    }
  }

  /*
  @type: function
  @purpose: To pay/charge a user for an assessment
  @param: address user = the user to pay/charge
  @param: int amount = the user's new token balance
  */
  function pay(address user, int amount)
  {
    if(assessmentExists[msg.sender] = true) //Checks if msg.sender is an existing assessment
    {
      UserMaster(userMaster).mapTokenBalance(user, amount); //Changes the user's token balance
    }
  }

  /*
  @type: function
  @purpose: to remove this contract
  @param: address receiver = the address of the wallet that will receive of the ether
  @returns: nothing
  */
  function remove(address reciever) onlyThis
  {
    suicide(reciever);
  }
}

import "lib/random.sol";
import "userMaster.sol";
import "assessment.sol";
import "user.sol";
import "tagMaster.sol";

/*
@type: contract
@name: Tag
@purpose: To store tag data and create and store information about assessments of this tag
*/
contract Tag
{
  address[] parentTags; //The tags that this tag is child to (ie: Calculus is child to Math)
  address[] childTags; //The tags that this tag is parent to (ie: Math is parent to Calculus)
  address userMaster; //The address of the userMaster contract
  address tagMaster; //The address of the tagMaster contract
  address random; //The address of the random contract
  string name; //The name of the tag
  int maxScore = 0; //The highest score acheived for this tag
  uint maxSize = 5; //The largest assessment taken for this tag
  address[] owners; //Those who have earned the tag
  address mew;
  mapping (address => address[]) assessmentHistory; //All assessments completed
  mapping (address => int) currentScores; //The most recent score of a user
  mapping (address => uint) assessmentSizes; //The most recent size of an assessment taken by a user
  mapping(address => bool) assessmentExists; //All existing assessments

  /*
  @type: modifier
  @name: onlyUserMaster
  @purpose: to only allow the UserMaster contract to call a function to which this modifier is applied
  */
  modifier onlyUserMaster
  {
    if(msg.sender != userMaster) //checks if msg.sender has the same address as userMaster
    {
      throw; //throws the function call if not
    }
  }

  /*
  @type: modifier
  @name: onlyTagMaster
  @purpose: to only allow the TagMaster contract to call a function to which this modifier is applied
  */
  modifier onlyTagMaster
  {
    if(msg.sender != tagMaster) //checks if msg.sender has the same address as tagMaster
    {
      throw; //throws the function call if not
    }
  }

  /*
  @type: modifier
  @name: onlyThis
  @purpose: to only allow the this contract to call a function to which this modifier is applied
  */
  modifier onlyThis
  {
    if(msg.sender != address(this)) //Checks if msg.sender is this contract
    {
      throw; //Throws out the function call if it isn't
    }
  }

  /*
  @type: event
  @name: CompletedAssessment
  @purpose: To build a database of completed assessments
  */
  event CompletedAssessment
  ( address _assessee, //The address of the user who took the assessment
    bool _pass, //Whether or not the assessee passed the assessment
    int _score, //The score of the assessee
    address _assessment); //The address of the assessment

  /*
  @type: constructor function
  @purpose: To initialize the Tag contract
  @param: string tagName = the name of the tagName
  @param: address[] parents = the addresses of the tag's parents
  @param: address userMasterAddress = the address of the UserMaster contract
  @param: address tagMasterAddress = the address of the TagMaster that spawned this user
  @param: address randomAddress = the address of the ransom contract
  @returns: nothing
  */
  function Tag(string tagName, address[] parents, address userMasterAddress, address tagMasterAddress, address randomAddress)
  {
    name = tagName; //sets to value of name to that of tagName
    parentTags = parents; //sets the value of parentTags to that of parents
    userMaster = userMasterAddress; //sets the value of userMaster to that of userMasterAddress
    random = randomAddress; //sets the value of random to that of randomAddress
    tagMaster = tagMasterAddress; //sets the vale of tagMaster to that of tagMasterAddress
  }

  /*
  @type: function
  @purpose: To set the first user for this tag
  @param: address firstUser = the address of the first user to own the tag
  @returns: nothing
  */
  function addUser(address user) onlyUserMaster
  {
    if(address(this) == mew)
    {
      owners.push(user); //If there aren't then firstUser is made to be an owner of this tag
    }
  }

  function setMew(address mewAddress) onlyTagMaster
  {
    mew = mewAddress;
  }

  /*
  @type: function
  @purpose: To get the most recent score of a user
  @param: address user = the user whose score is to be checked
  @returns: The user's most recent score in the form of an int
  */
  function getCurrentScore(address user) constant returns(int)
  {
    return currentScores[user];
  }

  /*
  @type: function
  @purpose: To get the size of the most recent asssessment of a user
  @param: address user = the user whose assessment size is to be checked
  @returns: The user's most recent assessment size in the form of an uint
  */
  function getAssessmentSize(address user) constant returns(uint)
  {
    return assessmentSizes[user];
  }

  /*
  @type: function
  @purpose: To get the owners of this tag
  @returns: The users that own this tag in the form of an array of addresses
  */
  function getOwners() constant returns(address[])
  {
    return owners;
  }

  /*
  @type: function
  @purpose: To get the number of owners of this tag
  @returns: The number of users that own this tag in the form of an uint
  */
  function getOwnerLength() constant returns(uint)
  {
    return owners.length;
  }

  /*
  @type: function
  @purpose: To get a specific owner of this tag
  @param: uint index = the index of the user in the owners array
  @returns: The user that owns this tag with that index in the form of an address
  */
  function getOwner(uint index) constant returns(address)
  {
    return owners[index];
  }

  /*
  @type: function
  @purpose: To get the parents of this tag
  @returns: The parents of this tag in the form of an array of addresses
  */
  function getParents() constant returns(address[])
  {
    return parentTags;
  }

  /*
  @type: function
  @purpose: To get the number of parents for this tag
  @returns: The number of parents for this tag in the form of an uint
  */
  function getParentsLength() constant returns(uint)
  {
    return parentTags.length;
  }

  /*
  @type: function
  @purpose: To get a specific parent of this tag
  @param: uint index = the index of the tag in the parentTags array
  @returns: The tag that is parent to this tag with that index in the form of an address
  */
  function getParent(uint index) constant returns(address)
  {
    return parentTags[index];
  }

  /*
  @type: function
  @purpose: To add a parent to the tag
  @param: address parentAddress = the address of the new parent tag
  @returns: nothing
  */
  function addParent(address parentAddress) onlyTagMaster
  {
    parentTags.push(parentAddress);
  }

  /*
  @type: function
  @purpose: To get the children of this tag
  @returns: The children of this tag in the form of an array of addresses
  */
  function getChildren() constant returns(address[])
  {
    return childTags;
  }

  /*
  @type: function
  @purpose: To get the number of children of this tag
  @returns: The number of children of this tag in the form of an uint
  */
  function getChildrenLength() constant returns(uint)
  {
    return childTags.length;
  }

  /*
  @type: function
  @purpose: To get a specific child of this tag
  @param: uint index = the index of the tag in the childTags array
  @returns: The tag that is child to this tag with that index in the form of an address
  */
  function getChild(uint index) constant returns(address)
  {
    return childTags[index];
  }

  /*
  @type: function
  @purpose: To add a child to the tag
  @param: address childAddress = the address of the new child tag
  @returns: nothing
  */
  function addChild(address childAddress) onlyTagMaster
  {
    childTags.push(childAddress);
  }

  /*
  @type: function
  @purpose: To get the name of this tag
  @returns: The name of the tag in the form of a string
  */
  function getName() returns(string)
  {
    return name;
  }

  /*
  @type: function
  @purpose: To recursively set the pool to draw assessors from in the assessment
  @param: address tagAddress = the tag that assessors are currently being drawn from
  @param: address assessment = the address of the assessment that assessors are being drawn for
  @param: uint seed = the seed number for random number generation
  @param: uint size = the desired size of the assessment
  @returns: nothing
  */
  function setAssessorPool(address tagAddress, address assessment, uint seed, uint size) onlyThis
  {
    if(Tag(TagMaster(tagMaster).getTagAddressFromName("mew")).getOwnerLength() < Assessment(assessment).getAssessmentPoolSize()) //Checks if the requested pool size is greater than the number of users in the system
    {
      for(uint i = 0; i < Tag(TagMaster(tagMaster).getTagAddressFromName("mew")).getOwnerLength(); i++) //If so, all users in the system are added to the pool
      {
        Assessment(assessment).addToAssessorPool(Tag(TagMaster(tagMaster).getTagAddressFromName("mew")).getOwner(i));
      }
      Assessment(assessment).setAssessmentPoolSize(0); //Sets the remaining amount of user's desired in the pool to 0
      Assessment(assessment).setPotentialAssessor(size); //Has the assessment select random potential assessors (the amount is dictated by the size variable)
    }
    for(uint j = 0; j < Tag(tagAddress).getOwnerLength() && Assessment(assessment).getAssessmentPoolSize() > 0; j++) //Iterates through all the owners of the tag corresponding to tag address while the remaining amount of user's desired in the pool is greater than 0
    {
      uint numberSet = 0; //initializes a variable to keep track of how many assessors this tag has added to the pool
      if(numberSet < Tag(tagAddress).getOwnerLength()/10) //Checks if the number of assessors provided by this tag is less than 10% of the owners of the tag
      {
        address randomUser = Tag(tagAddress).getOwner(Random(random).getRandom(seed + j, Tag(tagAddress).getOwnerLength()-1)); //gets a random owner of the tag
        if(UserMaster(userMaster).getAvailability(randomUser) == true && (uint(Tag(tagAddress).getCurrentScore(randomUser))*Tag(tagAddress).getAssessmentSize(randomUser)) > (now%(uint(maxScore)*maxSize))) //Checks if the randomly drawn is available and then puts it through a random check that it has a higher chance of passing if it has had a higher score and a larger assessment
        {
          Assessment(assessment).addToAssessorPool(randomUser); //adds the randomly selected user to the assessor pool
          Assessment(assessment).setAssessmentPoolSize(Assessment(assessment).getAssessmentPoolSize() -1); //reduces desired amount of users to be added to the assessor bool by 1
          numberSet++; //increases numberSet by 1
        }
      }
      else
      {
        break; //exits this for loop if 10% or more of the tag owners are in the assessment pool
      }
    }
    if(Assessment(assessment).getAssessmentPoolSize() <= 0) //Checks if the number of desired users remaining for the assessment pool is no greater than 0
    {
      Assessment(assessment).setPotentialAssessor(size); //If so, the assessment selects random potential assessors (the amount is dictated by the size variable)
    }
    else //If not
    {
      for(uint l = 0; l < Tag(tagAddress).getParentsLength() || l < Tag(tagAddress).getChildrenLength(); l++) //Recursively calls this function in such a way that the parent and child tags' owners will be used to potentially populate the assessment pool
      {
        if(l < Tag(tagAddress).getParentsLength()) //Makes sure there are still parent tags left to call
        {
          setAssessorPool(Tag(tagAddress).getParent(l), assessment, Random(random).getRandom(seed + l, Tag(tagAddress).getOwnerLength()-1), size);
        }
        if(l < Tag(tagAddress).getChildrenLength()) //Makes sure there are still child tags left to call
        {
          setAssessorPool(Tag(tagAddress).getChild(l), assessment, Random(random).getRandom(seed + l, Tag(tagAddress).getOwnerLength()-1), size);
        }
      }
    }
  }

  /*
  @type: function
  @purpose: To make a new assessment
  @param: address assessee = the address of the assessee
  @param: uint time = the time that assessors will have to assess in this assessment
  @param: uint size = the size of the assessment
  @returns: nothing
  */
  function makeAssessment(address assessee, uint time, uint size)
  {
    if(size >= 5) //Checks if the assessment has a size of at least 5
    {
      Assessment newAssessment = new Assessment(assessee, address(this), userMaster, tagMaster, random, time); //Makes a new assessment with the given parameters
      assessmentExists[address(newAssessment)] = true; //Sets the assessment's existance to true
      newAssessment.setNumberOfAssessors(size); //Sets the number of assessors wanted in the assessment to equal size
      newAssessment.setAssessmentPoolSize(size*20); //Sets the number of users wanted to form the assessor pool to 20 times size
    }
    else
    {
      throw; //Throws out the function call if the size of the assessment is less than 5
    }
  }

  /*
  @type: function
  @purpose: To start the assessment process
  @param: address assessment = the address of the assessment
  @returns: nothing
  */
  function startAssessment(address assessment)
  {
    if(block.number - Assessment(assessment).getReferenceBlock() >= 4 && block.number - Assessment(assessment).getReferenceBlock() <= 6) //Checks if this function is being called 4 to 6 blocks after the block in which the assessment was created
    {
      setAssessorPool(address(this), assessment, Assessment(assessment).getNumberOfAssessors(), Assessment(assessment).getNumberOfAssessors()); //Calls thge function to set the assessor pool
    }
    else
    {
      Assessment(assessment).cancelAssessment(); //If this function is called too early or too late the assessment is cancelled
    }
  }

  /*
  @type: function
  @purpose: To finish the assessment process
  @param: bool pass = whether or not the assessee passed the assessment
  @param: int score = the assessee's score
  @param: address assessee = the address of the assessee
  @param: address assessment = the address of the assessment
  @returns: nothing
  */
  function finishAssessment(bool pass, int score, address assessee, address assessment)
  {
    if(msg.sender == assessment) //Checks to make sure this function is being callled by the assessment
    {
      if(pass == true) //If the assessee passed
      {
        owners.push(assessee); //Makes the assessee an owner of this tag
        UserMaster(userMaster).mapAchievement(assessee,address(this)); //Maps the assessee to this tag in the user master as one of the assessee's achievments
      }
      assessmentHistory[assessee].push(assessment); //Adds the assessment to the assessment history array
      currentScores[assessee] = score; //Maps the assessee to their score
      assessmentSizes[assessee] = Assessment(assessment).getNumberOfAssessors(); //Maps the assessee to the assessment size
      if(score > maxScore)
      {
        maxScore = score; //If this assessment's score is higher that the current highest score than the maxScore variable is updated with this score
      }
      if(Assessment(assessment).getNumberOfAssessors() > maxSize)
      {
        maxSize = Assessment(assessment).getNumberOfAssessors(); //If this assessment's size is larger that the current largest assessment size than the maxSize variable is updated with this size
      }
      CompletedAssessment(assessee, pass, score, assessment); //Makes an event with this assessment's data
    }
  }

  /*
  @type: function
  @purpose: To pay/charge a user for an assessment
  @param: address user = the user to pay/charge
  @param: int amount = the user's new token balance
  */
  function pay(address user, int amount)
  {
    if(assessmentExists[msg.sender] = true) //Checks if msg.sender is an existing assessment
    {
      UserMaster(userMaster).mapTokenBalance(user, amount); //Changes the user's token balance
    }
  }

  /*
  @type: function
  @purpose: to remove this contract
  @param: address receiver = the address of the wallet that will receive of the ether
  @returns: nothing
  */
  function remove(address reciever) onlyThis
  {
    suicide(reciever);
  }
}


Allow languages to be recorded in Glofile.

/**
 * @title Glofile
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract Glofile {

  enum GlofileType { Anon, Person, Project, Organization, Proxy, Parody, Bot }
  enum SafetyLevel { Safe, NSFW, NSFL }

  struct Glofile {
    bool dontIndex;
    GlofileType glofileType;
    SafetyLevel safetyLevel;
    string fullName;
    string location;
    bytes3[] foregroundColors;
    bytes3[] backgroundColors;
    bytes3[] languages;
    bytes3[] bioLangs;
    bytes[] avatars;
    bytes[] coverImages;
    bytes[] backgroundImages;
    string[] topics;
    string[] parents;
    string[] children;
    string[] uris;
    mapping (bytes3 => bytes) bioTranslations;
  }

  mapping (address => Glofile) glofiles;

  event Update(address indexed account);
  event Delete(address indexed account);

  /**
   * @notice Set your Glofile don't index flag to `dontIndex`
   * @dev Sets the "don't index" flag. Glofiles with this flag set should only be accessible directly and not be discoverable via search.
   * @param dontIndex flag to indicate that this Glofile should not be indexed
   */
  function setDontIndex(bool dontIndex) {
    glofiles[msg.sender].dontIndex = dontIndex;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile type to `glofileType`
   * @dev Sets the Glofile type.
   * @param glofileType Glofile type
   */
  function setGlofileType(GlofileType glofileType) {
    glofiles[msg.sender].glofileType = glofileType;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile safety level to `safetyLevel`
   * @dev Sets the safety level. The account may publish content that is less safe than this, so long as it is flagged as such.
   * @param safetyLevel safety level
   */
  function setSafetyLevel(SafetyLevel safetyLevel) {
    glofiles[msg.sender].safetyLevel = safetyLevel;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile full name to `fullName`
   * @dev Sets the full name.
   * @param fullName UTF-8 string of full name - max length 128 chars
   */
  function setFullName(string fullName) {
    glofiles[msg.sender].fullName = fullName;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile location
   * @dev Sets the location. A dedicated contract could be used for more sophisticated location functionality.
   * @param location UTF-8 string of location - max string length 128 chars
   */
  function setLocation(string location) {
    glofiles[msg.sender].location = location;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile foreground colors
   * @dev Sets all the foreground colors.
   * @param colors array of RGB triplets
   */
  function setForegroundColors(bytes3[] colors) {
    glofiles[msg.sender].foregroundColors = colors;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile background colors
   * @dev Sets all the background colors.
   * @param colors array of RGB triplets
   */
  function setBackgroundColors(bytes3[] colors) {
    glofiles[msg.sender].backgroundColors = colors;
    Update(msg.sender);
  }

  /**
   * @notice Sets the Glofile langauges your account may publish in
   * @dev Sets all the languages the account may publish in.
   * @param languages array of 3 letter ISO 639-3 language codes
   */
  function setLanguages(bytes3[] languages) {
    glofiles[msg.sender].languages = languages;
    Update(msg.sender);
  }

  /**
   * @notice Get Glofile basic info
   * @dev Gets all the info that can be retreived in a single call.
   * @param account Glofile to access
   * @return dontIndex flag to indicate that this Glofile should not be indexed
   * @return glofileType Glofile type
   * @return safetyLevel safety level
   * @return fullName UTF-8 string of full name
   * @return location UTF-8 string of location
   * @return foregroundColors array of RGB triplets of foreground colors
   * @return backgroundColors array of RGB triplets of background colors
   * @return languages array of 3 letter ISO 639-3 language codes
   */
  function getBasicInfo(address account) constant returns (bool dontIndex, GlofileType glofileType, SafetyLevel safetyLevel, string fullName, string location, bytes3[] foregroundColors, bytes3[] backgroundColors, bytes3[] languages) {
    Glofile glofile = glofiles[account];
    dontIndex = glofile.dontIndex;
    glofileType = glofile.glofileType;
    safetyLevel = glofile.safetyLevel;
    fullName = glofile.fullName;
    location = glofile.location;
    foregroundColors = glofile.foregroundColors;
    backgroundColors = glofile.backgroundColors;
    languages = glofile.languages;
  }

  /**
   * @notice Set your Glofile bio with langauge code `lang`
   * @dev Sets the bio in a specific language.
   * @param lang 3 letter ISO 639-3 language code
   * @param translation UTF-8 Markdown of bio compressed with DEFLATE - max Markdown length 256 chars
   */
  function setBio(bytes3 lang, bytes translation) {
    Glofile glofile = glofiles[msg.sender];
    // Check if we already have the language code.
    for (uint i = 0; i < glofile.bioLangs.length; i++) {
      if (glofile.bioLangs[i] == lang) {
        break;
      }
    }
    if (i == glofile.bioLangs.length) {
      // We didn't find it. Try to find a free slot.
      for (i = 0; i < glofile.bioLangs.length; i++) {
        if (glofile.bioLangs[i] == 0) {
          break;
        }
      }
      if (i == glofile.bioLangs.length) {
        // We didn't find a free slot. Make the array bigger.
        glofile.bioLangs.length++;
      }
      glofile.bioLangs[i] = lang;
    }
    // Set translation.
    glofile.bioTranslations[lang] = translation;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile bio with language code `lang`
   * @dev Deletes a bio translation.
   * @param lang 3 letter ISO 639-3 language code
   */
  function deleteBio(bytes3 lang) {
    Glofile glofile = glofiles[msg.sender];
    for (uint i = 0; i < glofile.bioLangs.length; i++) {
      if (glofile.bioLangs[i] == lang) {
        delete glofile.bioLangs[i];
        break;
      }
    }
    // Delete the actual mapping in case a client accesses without checking
    // language key.
    delete glofile.bioTranslations[lang];
    Update(msg.sender);
  }

  /**
   * @notice Delete all of your Glofile bio translations
   * @dev Deletes all of the bio translations.
   */
  function deleteAllBioTranslations() {
    Glofile glofile = glofiles[msg.sender];
    // Delete the actual mappings in case a client accesses without checking
    // language key.
    for (uint i = 0; i < glofile.bioLangs.length; i++) {
      delete glofile.bioTranslations[glofile.bioLangs[i]];
    }
    delete glofile.bioLangs;
    Update(msg.sender);
  }

  /**
   * @notice Get the list of language code a Glofile bio is available in
   * @dev Gets the list of language codes the bio is available in.
   * @param account Glofile to access
   * @return array of 3 letter ISO 639-3 language codes
   */
  function getBioLangCodes(address account) constant returns (bytes3[]) {
    return glofiles[account].bioLangs;
  }

  /**
   * @notice Get the Glofile bio with language code `lang`
   * @dev Gets the bio in a specific language.
   * @param account Glofile to access
   * @param lang 3 letter ISO 639-3 language code
   * @return UTF-8 Markdown of bio compressed with DEFLATE
   */
  function getBio(address account, bytes3 lang) constant returns (bytes) {
    return glofiles[account].bioTranslations[lang];
  }

  /**
   * @notice Set your Glofile avatar with index `i` to `ipfsHash`
   * @dev Sets the avatar with a specific index to an IPFS hash.
   * @param i index of avatar to set
   * @param ipfsHash binary IPFS hash of image
   */
  function setAvatar(uint i, bytes ipfsHash) {
    bytes[] avatars = glofiles[msg.sender].avatars;
    // Make sure the array is long enough.
    if (avatars.length <= i) {
      avatars.length = i + 1;
    }
    avatars[i] = ipfsHash;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile avatar with index `i`
   * @dev Deletes an avatar with a specific index.
   * @param i index of avatar to delete
   */
  function deleteAvatar(uint i) {
    delete glofiles[msg.sender].avatars[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile avatars
   * @dev Deletes all avatars from the Glofile.
   */
  function deleteAllAvatars() {
    delete glofiles[msg.sender].avatars;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile avatars
   * @dev Gets the number of avatars.
   * @param account Glofile to access
   * @return number of avatars
   */
  function getAvatarCount(address account) constant returns (uint) {
    return glofiles[account].avatars.length;
  }

  /**
   * @notice Get the Glofile avatar with index `i`
   * @dev Gets the avatar with a specific index.
   * @param account Glofile to access
   * @param i index of avatar to get
   * @return binary IPFS hash of image
   */
  function getAvatar(address account, uint i) constant returns (bytes) {
    return glofiles[account].avatars[i];
  }

  /**
   * @notice Set your Glofile cover image with index `i` to `ipfsHash`
   * @dev Sets the cover image with a specific index to an IPFS hash.
   * @param i index of cover image to set
   * @param ipfsHash binary IPFS hash of image
   */
  function setCoverImage(uint i, bytes ipfsHash) {
    bytes[] coverImages = glofiles[msg.sender].coverImages;
    // Make sure the array is long enough.
    if (coverImages.length <= i) {
      coverImages.length = i + 1;
    }
    coverImages[i] = ipfsHash;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile cover image with index `i`
   * @dev Deletes the cover image with a specific index.
   * @param i index of cover image to delete
   */
  function deleteCoverImage(uint i) {
    delete glofiles[msg.sender].coverImages[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile cover images
   * @dev Deletes all cover images from the Glofile.
   */
  function deleteAllCoverImages() {
    delete glofiles[msg.sender].coverImages;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile cover images
   * @dev Gets the number of cover images.
   * @param account Glofile to access
   * @return number of cover images
   */
  function getCoverImageCount(address account) constant returns (uint) {
    return glofiles[account].coverImages.length;
  }

  /**
   * @notice Get the Glofile cover image with index `i`
   * @dev Gets the cover image with a specific index.
   * @param account Glofile to access
   * @param i index of cover image to get
   * @return binary IPFS hash of image
   */
  function getCoverImage(address account, uint i) constant returns (bytes) {
    return glofiles[account].coverImages[i];
  }

  /**
   * @notice Set your Glofile background image with index `i` to `ipfsHash`
   * @dev Sets the background image with a specific index to an IPFS hash.
   * @param i index of background image to set
   * @param ipfsHash binary IPFS hash of image
   */
  function setBackgroundImage(uint i, bytes ipfsHash) {
    bytes[] backgroundImages = glofiles[msg.sender].backgroundImages;
    // Make sure the array is long enough.
    if (backgroundImages.length <= i) {
      backgroundImages.length = i + 1;
    }
    backgroundImages[i] = ipfsHash;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile background image with index `i`
   * @dev Deletes the background image with a specific index.
   * @param i index of background image to delete
   */
  function deleteBackgroundImage(uint i) {
    delete glofiles[msg.sender].backgroundImages[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile background images
   * @dev Deletes all the background images.
   */
  function deleteAllBackgroundImages() {
    delete glofiles[msg.sender].backgroundImages;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile background images
   * @dev Gets the number of background images.
   * @param account Glofile to access
   * @return number of background images
   */
  function getBackgroundImageCount(address account) constant returns (uint) {
    return glofiles[account].backgroundImages.length;
  }

  /**
   * @notice Get the Glofile background image with index `i`
   * @dev Gets the background image with a specific index.
   * @param i index of cover image to get
   * @param account Glofile to access
   * @return binary IPFS hash of image
   */
  function getBackgroundImage(address account, uint i) constant returns (bytes) {
    return glofiles[account].backgroundImages[i];
  }

  /**
   * @notice Set your Glofile topic with index `i` to `topic`
   * @dev Sets the topic with a specific index.
   * @param i index of topic to set
   * @param topic UTF-8 string of topic (no whitespace)
   */
  function setTopic(uint i, string topic) {
    string[] topics = glofiles[msg.sender].topics;
    // Make sure the array is long enough.
    if (topics.length <= i) {
      topics.length = i + 1;
    }
    topics[i] = topic;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile topic with index `i`
   * @dev Deletes an topic with a specific index.
   * @param i index of topic to delete
   */
  function deleteTopic(uint i) {
    delete glofiles[msg.sender].topics[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile topics
   * @dev Deletes all topics from the Glofile.
   */
  function deleteAllTopics() {
    delete glofiles[msg.sender].topics;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile topics
   * @dev Gets the number of topics.
   * @param account Glofile to access
   * @return number of topics
   */
  function getTopicCount(address account) constant returns (uint) {
    return glofiles[account].topics.length;
  }

  /**
   * @notice Get the Glofile topic with index `i`
   * @dev Gets the topic with a specific index.
   * @param account Glofile to access
   * @param i index of topic to get
   * @return UTF-8 string of topic
   */
  function getTopic(address account, uint i) constant returns (string) {
    return glofiles[account].topics[i];
  }

  /**
   * @notice Set your Glofile parent with index `i` to `parent`
   * @dev Sets the parent with a specific index.
   * @param i index of parent to set
   * @param parent UTF-8 string of parent
   */
  function setParent(uint i, string parent) {
    string[] parents = glofiles[msg.sender].parents;
    // Make sure the array is long enough.
    if (parents.length <= i) {
      parents.length = i + 1;
    }
    parents[i] = parent;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile parent with index `i`
   * @dev Deletes an parent with a specific index.
   * @param i index of parent to delete
   */
  function deleteParent(uint i) {
    delete glofiles[msg.sender].parents[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile parents
   * @dev Deletes all parents from the Glofile.
   */
  function deleteAllParents() {
    delete glofiles[msg.sender].parents;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile parents
   * @dev Gets the number of parents.
   * @param account Glofile to access
   * @return number of parents
   */
  function getParentCount(address account) constant returns (uint) {
    return glofiles[account].parents.length;
  }

  /**
   * @notice Get the Glofile parent with index `i`
   * @dev Gets the parent with a specific index.
   * @param account Glofile to access
   * @param i index of parent to get
   * @return UTF-8 string of parent
   */
  function getParent(address account, uint i) constant returns (string) {
    return glofiles[account].parents[i];
  }

  /**
   * @notice Set your Glofile child with index `i` to `child`
   * @dev Sets the child with a specific index.
   * @param i index of child to set
   * @param child UTF-8 string of child
   */
  function setChild(uint i, string child) {
    string[] children = glofiles[msg.sender].children;
    // Make sure the array is long enough.
    if (children.length <= i) {
      children.length = i + 1;
    }
    children[i] = child;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile child with index `i`
   * @dev Deletes an child with a specific index.
   * @param i index of child to delete
   */
  function deleteChild(uint i) {
    delete glofiles[msg.sender].children[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile children
   * @dev Deletes all children from the Glofile.
   */
  function deleteAllChildren() {
    delete glofiles[msg.sender].children;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile children
   * @dev Gets the number of children.
   * @param account Glofile to access
   * @return number of children
   */
  function getChildCount(address account) constant returns (uint) {
    return glofiles[account].children.length;
  }

  /**
   * @notice Get the Glofile child with index `i`
   * @dev Gets the child with a specific index.
   * @param account Glofile to access
   * @param i index of child to get
   * @return UTF-8 string of child
   */
  function getChild(address account, uint i) constant returns (string) {
    return glofiles[account].children[i];
  }

  /**
   * @notice Set your Glofile uri with index `i` to `uri`
   * @dev Sets the uri with a specific index.
   * @param i index of uri to set
   * @param uri UTF-8 string of uri
   */
  function setUri(uint i, string uri) {
    string[] uris = glofiles[msg.sender].uris;
    // Make sure the array is long enough.
    if (uris.length <= i) {
      uris.length = i + 1;
    }
    uris[i] = uri;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile uri with index `i`
   * @dev Deletes an uri with a specific index.
   * @param i index of uri to delete
   */
  function deleteUri(uint i) {
    delete glofiles[msg.sender].uris[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile uris
   * @dev Deletes all uris from the Glofile.
   */
  function deleteAllUris() {
    delete glofiles[msg.sender].uris;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile uris
   * @dev Gets the number of uris.
   * @param account Glofile to access
   * @return number of uris
   */
  function getUriCount(address account) constant returns (uint) {
    return glofiles[account].uris.length;
  }

  /**
   * @notice Get the Glofile uri with index `i`
   * @dev Gets the uri with a specific index.
   * @param account Glofile to access
   * @param i index of uri to get
   * @return UTF-8 string of uri
   */
  function getUri(address account, uint i) constant returns (string) {
    return glofiles[account].uris[i];
  }

  /**
   * @notice Copy entire Glofile from `source`
   * @dev Copies the Glofile from another account to this one.
   * @param source account of Glofile to copy from
   * TODO: check this works
   */
  function copyEntireGlofile(address source) {
    glofiles[msg.sender] = glofiles[source];
    Update(msg.sender);
  }

  /**
   * @notice Delete your entire Glofile
   * @dev Deletes the Glofile completely.
   * TODO: make sure this deletes everything
   */
  function deleteEntireGlofile() {
    delete glofiles[msg.sender];
    Delete(msg.sender);
  }

}

/**
 * @title Glofile
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract Glofile {

  enum GlofileType { Anon, Person, Project, Organization, Proxy, Parody, Bot }
  enum SafetyLevel { Safe, NSFW, NSFL }

  struct Glofile {
    bool dontIndex;
    GlofileType glofileType;
    SafetyLevel safetyLevel;
    string fullName;
    string location;
    bytes3[] foregroundColors;
    bytes3[] backgroundColors;
    bytes3[] bioLangs;
    bytes[] avatars;
    bytes[] coverImages;
    bytes[] backgroundImages;
    string[] topics;
    string[] parents;
    string[] children;
    string[] uris;
    mapping (bytes3 => bytes) bioTranslations;
  }

  mapping (address => Glofile) glofiles;

  event Update(address indexed account);
  event Delete(address indexed account);

  /**
   * @notice Set your Glofile don't index flag to `dontIndex`
   * @dev Sets the "don't index" flag. Glofiles with this flag set should only be accessible directly and not be discoverable via search.
   * @param dontIndex flag to indicate that this Glofile should not be indexed
   */
  function setDontIndex(bool dontIndex) {
    glofiles[msg.sender].dontIndex = dontIndex;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile type to `glofileType`
   * @dev Sets the Glofile type.
   * @param glofileType Glofile type
   */
  function setGlofileType(GlofileType glofileType) {
    glofiles[msg.sender].glofileType = glofileType;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile safety level to `safetyLevel`
   * @dev Sets the safety level. The account may publish content that is less safe than this, so long as it is flagged as such.
   * @param safetyLevel safety level
   */
  function setSafetyLevel(SafetyLevel safetyLevel) {
    glofiles[msg.sender].safetyLevel = safetyLevel;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile full name to `fullName`
   * @dev Sets the full name.
   * @param fullName UTF-8 string of full name - max length 128 chars
   */
  function setFullName(string fullName) {
    glofiles[msg.sender].fullName = fullName;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile location
   * @dev Sets the location. A dedicated contract could be used for more sophisticated location functionality.
   * @param location UTF-8 string of location - max string length 128 chars
   */
  function setLocation(string location) {
    glofiles[msg.sender].location = location;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile foreground colors
   * @dev Sets all the foreground colors.
   * @param colors array of RGB triplets
   */
  function setForegroundColors(bytes3[] colors) {
    glofiles[msg.sender].foregroundColors = colors;
    Update(msg.sender);
  }

  /**
   * @notice Set your Glofile background colors
   * @dev Sets all the background colors.
   * @param colors array of RGB triplets
   */
  function setBackgroundColors(bytes3[] colors) {
    glofiles[msg.sender].backgroundColors = colors;
    Update(msg.sender);
  }

  /**
   * @notice Get Glofile basic info
   * @dev Gets all the info that can be retreived in a single call.
   * @param account Glofile to access
   * @return dontIndex flag to indicate that this Glofile should not be indexed
   * @return glofileType Glofile type
   * @return safetyLevel safety level
   * @return fullName UTF-8 string of full name
   * @return location UTF-8 string of location
   * @return foregroundColors array of RGB triplets of foreground colors
   * @return backgroundColors array of RGB triplets of background colors
   */
  function getBasicInfo(address account) constant returns (bool dontIndex, GlofileType glofileType, SafetyLevel safetyLevel, string fullName, string location, bytes3[] foregroundColors, bytes3[] backgroundColors) {
    Glofile glofile = glofiles[account];
    dontIndex = glofile.dontIndex;
    glofileType = glofile.glofileType;
    safetyLevel = glofile.safetyLevel;
    fullName = glofile.fullName;
    location = glofile.location;
    foregroundColors = glofile.foregroundColors;
    backgroundColors = glofile.backgroundColors;
  }

  /**
   * @notice Set your Glofile bio with langauge code `lang`
   * @dev Sets the bio in a specific language.
   * @param lang 3 letter ISO 639-3 language code
   * @param translation UTF-8 Markdown of bio compressed with DEFLATE - max Markdown length 256 chars
   */
  function setBio(bytes3 lang, bytes translation) {
    Glofile glofile = glofiles[msg.sender];
    // Check if we already have the language code.
    for (uint i = 0; i < glofile.bioLangs.length; i++) {
      if (glofile.bioLangs[i] == lang) {
        break;
      }
    }
    if (i == glofile.bioLangs.length) {
      // We didn't find it. Try to find a free slot.
      for (i = 0; i < glofile.bioLangs.length; i++) {
        if (glofile.bioLangs[i] == 0) {
          break;
        }
      }
      if (i == glofile.bioLangs.length) {
        // We didn't find a free slot. Make the array bigger.
        glofile.bioLangs.length++;
      }
      glofile.bioLangs[i] = lang;
    }
    // Set translation.
    glofile.bioTranslations[lang] = translation;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile bio with language code `lang`
   * @dev Deletes a bio translation.
   * @param lang 3 letter ISO 639-3 language code
   */
  function deleteBio(bytes3 lang) {
    Glofile glofile = glofiles[msg.sender];
    for (uint i = 0; i < glofile.bioLangs.length; i++) {
      if (glofile.bioLangs[i] == lang) {
        delete glofile.bioLangs[i];
        break;
      }
    }
    // Delete the actual mapping in case a client accesses without checking
    // language key.
    delete glofile.bioTranslations[lang];
    Update(msg.sender);
  }

  /**
   * @notice Delete all of your Glofile bio translations
   * @dev Deletes all of the bio translations.
   */
  function deleteAllBioTranslations() {
    Glofile glofile = glofiles[msg.sender];
    // Delete the actual mappings in case a client accesses without checking
    // language key.
    for (uint i = 0; i < glofile.bioLangs.length; i++) {
      delete glofile.bioTranslations[glofile.bioLangs[i]];
    }
    delete glofile.bioLangs;
    Update(msg.sender);
  }

  /**
   * @notice Get the list of language code a Glofile bio is available in
   * @dev Gets the list of language codes the bio is available in.
   * @param account Glofile to access
   * @return array of 3 letter ISO 639-3 language codes
   */
  function getBioLangCodes(address account) constant returns (bytes3[]) {
    return glofiles[account].bioLangs;
  }

  /**
   * @notice Get the Glofile bio with language code `lang`
   * @dev Gets the bio in a specific language.
   * @param account Glofile to access
   * @param lang 3 letter ISO 639-3 language code
   * @return UTF-8 Markdown of bio compressed with DEFLATE
   */
  function getBio(address account, bytes3 lang) constant returns (bytes) {
    return glofiles[account].bioTranslations[lang];
  }

  /**
   * @notice Set your Glofile avatar with index `i` to `ipfsHash`
   * @dev Sets the avatar with a specific index to an IPFS hash.
   * @param i index of avatar to set
   * @param ipfsHash binary IPFS hash of image
   */
  function setAvatar(uint i, bytes ipfsHash) {
    bytes[] avatars = glofiles[msg.sender].avatars;
    // Make sure the array is long enough.
    if (avatars.length <= i) {
      avatars.length = i + 1;
    }
    avatars[i] = ipfsHash;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile avatar with index `i`
   * @dev Deletes an avatar with a specific index.
   * @param i index of avatar to delete
   */
  function deleteAvatar(uint i) {
    delete glofiles[msg.sender].avatars[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile avatars
   * @dev Deletes all avatars from the Glofile.
   */
  function deleteAllAvatars() {
    delete glofiles[msg.sender].avatars;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile avatars
   * @dev Gets the number of avatars.
   * @param account Glofile to access
   * @return number of avatars
   */
  function getAvatarCount(address account) constant returns (uint) {
    return glofiles[account].avatars.length;
  }

  /**
   * @notice Get the Glofile avatar with index `i`
   * @dev Gets the avatar with a specific index.
   * @param account Glofile to access
   * @param i index of avatar to get
   * @return binary IPFS hash of image
   */
  function getAvatar(address account, uint i) constant returns (bytes) {
    return glofiles[account].avatars[i];
  }

  /**
   * @notice Set your Glofile cover image with index `i` to `ipfsHash`
   * @dev Sets the cover image with a specific index to an IPFS hash.
   * @param i index of cover image to set
   * @param ipfsHash binary IPFS hash of image
   */
  function setCoverImage(uint i, bytes ipfsHash) {
    bytes[] coverImages = glofiles[msg.sender].coverImages;
    // Make sure the array is long enough.
    if (coverImages.length <= i) {
      coverImages.length = i + 1;
    }
    coverImages[i] = ipfsHash;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile cover image with index `i`
   * @dev Deletes the cover image with a specific index.
   * @param i index of cover image to delete
   */
  function deleteCoverImage(uint i) {
    delete glofiles[msg.sender].coverImages[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile cover images
   * @dev Deletes all cover images from the Glofile.
   */
  function deleteAllCoverImages() {
    delete glofiles[msg.sender].coverImages;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile cover images
   * @dev Gets the number of cover images.
   * @param account Glofile to access
   * @return number of cover images
   */
  function getCoverImageCount(address account) constant returns (uint) {
    return glofiles[account].coverImages.length;
  }

  /**
   * @notice Get the Glofile cover image with index `i`
   * @dev Gets the cover image with a specific index.
   * @param account Glofile to access
   * @param i index of cover image to get
   * @return binary IPFS hash of image
   */
  function getCoverImage(address account, uint i) constant returns (bytes) {
    return glofiles[account].coverImages[i];
  }

  /**
   * @notice Set your Glofile background image with index `i` to `ipfsHash`
   * @dev Sets the background image with a specific index to an IPFS hash.
   * @param i index of background image to set
   * @param ipfsHash binary IPFS hash of image
   */
  function setBackgroundImage(uint i, bytes ipfsHash) {
    bytes[] backgroundImages = glofiles[msg.sender].backgroundImages;
    // Make sure the array is long enough.
    if (backgroundImages.length <= i) {
      backgroundImages.length = i + 1;
    }
    backgroundImages[i] = ipfsHash;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile background image with index `i`
   * @dev Deletes the background image with a specific index.
   * @param i index of background image to delete
   */
  function deleteBackgroundImage(uint i) {
    delete glofiles[msg.sender].backgroundImages[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile background images
   * @dev Deletes all the background images.
   */
  function deleteAllBackgroundImages() {
    delete glofiles[msg.sender].backgroundImages;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile background images
   * @dev Gets the number of background images.
   * @param account Glofile to access
   * @return number of background images
   */
  function getBackgroundImageCount(address account) constant returns (uint) {
    return glofiles[account].backgroundImages.length;
  }

  /**
   * @notice Get the Glofile background image with index `i`
   * @dev Gets the background image with a specific index.
   * @param i index of cover image to get
   * @param account Glofile to access
   * @return binary IPFS hash of image
   */
  function getBackgroundImage(address account, uint i) constant returns (bytes) {
    return glofiles[account].backgroundImages[i];
  }

  /**
   * @notice Set your Glofile topic with index `i` to `topic`
   * @dev Sets the topic with a specific index.
   * @param i index of topic to set
   * @param topic UTF-8 string of topic (no whitespace)
   */
  function setTopic(uint i, string topic) {
    string[] topics = glofiles[msg.sender].topics;
    // Make sure the array is long enough.
    if (topics.length <= i) {
      topics.length = i + 1;
    }
    topics[i] = topic;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile topic with index `i`
   * @dev Deletes an topic with a specific index.
   * @param i index of topic to delete
   */
  function deleteTopic(uint i) {
    delete glofiles[msg.sender].topics[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile topics
   * @dev Deletes all topics from the Glofile.
   */
  function deleteAllTopics() {
    delete glofiles[msg.sender].topics;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile topics
   * @dev Gets the number of topics.
   * @param account Glofile to access
   * @return number of topics
   */
  function getTopicCount(address account) constant returns (uint) {
    return glofiles[account].topics.length;
  }

  /**
   * @notice Get the Glofile topic with index `i`
   * @dev Gets the topic with a specific index.
   * @param account Glofile to access
   * @param i index of topic to get
   * @return UTF-8 string of topic
   */
  function getTopic(address account, uint i) constant returns (string) {
    return glofiles[account].topics[i];
  }

  /**
   * @notice Set your Glofile parent with index `i` to `parent`
   * @dev Sets the parent with a specific index.
   * @param i index of parent to set
   * @param parent UTF-8 string of parent
   */
  function setParent(uint i, string parent) {
    string[] parents = glofiles[msg.sender].parents;
    // Make sure the array is long enough.
    if (parents.length <= i) {
      parents.length = i + 1;
    }
    parents[i] = parent;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile parent with index `i`
   * @dev Deletes an parent with a specific index.
   * @param i index of parent to delete
   */
  function deleteParent(uint i) {
    delete glofiles[msg.sender].parents[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile parents
   * @dev Deletes all parents from the Glofile.
   */
  function deleteAllParents() {
    delete glofiles[msg.sender].parents;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile parents
   * @dev Gets the number of parents.
   * @param account Glofile to access
   * @return number of parents
   */
  function getParentCount(address account) constant returns (uint) {
    return glofiles[account].parents.length;
  }

  /**
   * @notice Get the Glofile parent with index `i`
   * @dev Gets the parent with a specific index.
   * @param account Glofile to access
   * @param i index of parent to get
   * @return UTF-8 string of parent
   */
  function getParent(address account, uint i) constant returns (string) {
    return glofiles[account].parents[i];
  }

  /**
   * @notice Set your Glofile child with index `i` to `child`
   * @dev Sets the child with a specific index.
   * @param i index of child to set
   * @param child UTF-8 string of child
   */
  function setChild(uint i, string child) {
    string[] children = glofiles[msg.sender].children;
    // Make sure the array is long enough.
    if (children.length <= i) {
      children.length = i + 1;
    }
    children[i] = child;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile child with index `i`
   * @dev Deletes an child with a specific index.
   * @param i index of child to delete
   */
  function deleteChild(uint i) {
    delete glofiles[msg.sender].children[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile children
   * @dev Deletes all children from the Glofile.
   */
  function deleteAllChildren() {
    delete glofiles[msg.sender].children;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile children
   * @dev Gets the number of children.
   * @param account Glofile to access
   * @return number of children
   */
  function getChildCount(address account) constant returns (uint) {
    return glofiles[account].children.length;
  }

  /**
   * @notice Get the Glofile child with index `i`
   * @dev Gets the child with a specific index.
   * @param account Glofile to access
   * @param i index of child to get
   * @return UTF-8 string of child
   */
  function getChild(address account, uint i) constant returns (string) {
    return glofiles[account].children[i];
  }

  /**
   * @notice Set your Glofile uri with index `i` to `uri`
   * @dev Sets the uri with a specific index.
   * @param i index of uri to set
   * @param uri UTF-8 string of uri
   */
  function setUri(uint i, string uri) {
    string[] uris = glofiles[msg.sender].uris;
    // Make sure the array is long enough.
    if (uris.length <= i) {
      uris.length = i + 1;
    }
    uris[i] = uri;
    Update(msg.sender);
  }

  /**
   * @notice Delete your Glofile uri with index `i`
   * @dev Deletes an uri with a specific index.
   * @param i index of uri to delete
   */
  function deleteUri(uint i) {
    delete glofiles[msg.sender].uris[i];
    Update(msg.sender);
  }

  /**
   * @notice Delete all your Glofile uris
   * @dev Deletes all uris from the Glofile.
   */
  function deleteAllUris() {
    delete glofiles[msg.sender].uris;
    Update(msg.sender);
  }

  /**
   * @notice Get the number of Glofile uris
   * @dev Gets the number of uris.
   * @param account Glofile to access
   * @return number of uris
   */
  function getUriCount(address account) constant returns (uint) {
    return glofiles[account].uris.length;
  }

  /**
   * @notice Get the Glofile uri with index `i`
   * @dev Gets the uri with a specific index.
   * @param account Glofile to access
   * @param i index of uri to get
   * @return UTF-8 string of uri
   */
  function getUri(address account, uint i) constant returns (string) {
    return glofiles[account].uris[i];
  }

  /**
   * @notice Copy entire Glofile from `source`
   * @dev Copies the Glofile from another account to this one.
   * @param source account of Glofile to copy from
   * TODO: check this works
   */
  function copyEntireGlofile(address source) {
    glofiles[msg.sender] = glofiles[source];
    Update(msg.sender);
  }

  /**
   * @notice Delete your entire Glofile
   * @dev Deletes the Glofile completely.
   * TODO: make sure this deletes everything
   */
  function deleteEntireGlofile() {
    delete glofiles[msg.sender];
    Delete(msg.sender);
  }

}


Added line that allows tag contract to add user address to master achievement mapping when user successfully obtains tag.

contract Master
{
  function Master()
  {

  }
  //Initialize master data store
  mapping(address => uint) tokenBalance;
  mapping(address => string) tagName;
  mapping(string => address) tagAddress;
  mapping(address => Tag) tagImplementation;
  mapping(address => string[]) acheivements;

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddress[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag;
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddress[name] = newTagAddress;
      tagImplementation[newTagAddress] = newTag;
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i],tagImplementation[parentList[i]]);
        }
      }
    }
    newTag.setMaster(this);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parents; //The tags this is a subset of
  Tag[] parentTags;
  Master master;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores
  function Tag()
  {

  }
  function addParent(address parent, Tag parentTag)
  {
    parents.push(parent);
    parentTags.push(parentTag);
  }
  function setMaster(Master m)
  {
    master = m;
  }
  function getAssessors(uint randomNumber)
  {

  }
  function startAssessment(address assessee, address[] assessors)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setAssessors(assessors);
    newAssessment.setTag(this);
  }
  function getAssessmentResults(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      master.acheivements[assessee].push(master.tagName[address(this)]);
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessors;
  Tag tag;
  mapping(address => uint[]) assessmentData; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => bool[]) assessmentResults; //Pass/Fail given by assessors
  mapping(address => uint[]) assessmentScores; //Numerical score given by assessors

  function Assessment()
  {

  }
  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }
  function setAssessors(address[] newAssessors)
  {
    assessors = newAssessors;
  }
  function setTag(Tag t)
  {
    tag = t;
  }
  function assess()
  {

  }
  function cashout()
  {

  }
}

contract Master
{
  function Master()
  {

  }
  //Initialize master data store
  mapping(address => uint) tokenBalance;
  mapping(address => string) tagName;
  mapping(string => address) tagAddress;
  mapping(address => Tag) tagImplementation;
  mapping(address => string[]) acheivements;

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddress[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag;
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddress[name] = newTagAddress;
      tagImplementation[newTagAddress] = newTag;
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i],tagImplementation[parentList[i]]);
        }
      }
    }
    newTag.setMaster(this);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parents; //The tags this is a subset of
  Tag[] parentTags;
  Master master;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores
  function Tag()
  {

  }
  function addParent(address parent, Tag parentTag)
  {
    parents.push(parent);
    parentTags.push(parentTag);
  }
  function setMaster(Master m)
  {
    master = m;
  }
  function getAssessors(uint randomNumber)
  {

  }
  function startAssessment(address assessee, address[] assessors)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setAssessors(assessors);
    newAssessment.setTag(this);
  }
  function getAssessmentResults(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessors;
  Tag tag;
  mapping(address => uint[]) assessmentData; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => bool[]) assessmentResults; //Pass/Fail given by assessors
  mapping(address => uint[]) assessmentScores; //Numerical score given by assessors

  function Assessment()
  {

  }
  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }
  function setAssessors(address[] newAssessors)
  {
    assessors = newAssessors;
  }
  function setTag(Tag t)
  {
    tag = t;
  }
  function assess()
  {

  }
  function cashout()
  {

  }
}