void ResultQueue::Add( const Result& res ) {
  if( res.mode == MODE_SOLO_ADVENTURES ) {
    LOG( "Ignore solo adventure" );
    return;
  }

  if( res.mode == MODE_TAVERN_BRAWL ) {
    LOG( "Ignore tavern brawl" );
    return;
  }

  if( res.outcome == OUTCOME_UNKNOWN ) {
    LOG( "Outcome unknown. Skip result" );
    METADATA( "PREVIOUS_RESULT_INVALID", "OUTCOME" );
    return;
  }

  if( res.mode == MODE_UNKNOWN ) {
    LOG( "Mode unknown. Skip result" );
    METADATA( "PREVIOUS_RESULT_INVALID", "MODE" );
    return;
  }

  if( res.order == ORDER_UNKNOWN ) {
    LOG( "Order unknown. Skip result" );
    METADATA( "PREVIOUS_RESULT_INVALID", "ORDER" );
    return;
  }

  if( res.hero == CLASS_UNKNOWN ) {
    LOG( "Own Class unknown. Skip result" );
    METADATA( "PREVIOUS_RESULT_INVALID", "OWN_CLASS" );
    return;
  }

  if( res.opponent == CLASS_UNKNOWN ) {
    LOG( "Class of Opponent unknown. Skip result" );
    METADATA( "PREVIOUS_RESULT_INVALID", "OPPONENT_CLASS" );
    return;
  }

  // Clear some metadata if mode not ranked
  for( auto it : Metadata::Instance()->Map().toStdMap() ) {
    const QString& key = it.first;

    // Skip rank classification metadata for nonranked games
    if( key.startsWith( "RANK_CLASSIFIER" ) && res.mode != MODE_RANKED ) {
      Metadata::Instance()->Remove( key );
    }
  }

  LOG( "Result: %s %s vs. %s as %s. Went %s",
      MODE_NAMES[ res.mode ],
      OUTCOME_NAMES[ res.outcome ],
      CLASS_NAMES[ res.opponent ],
      CLASS_NAMES[ res.hero ],
      ORDER_NAMES[ res.order ] );

  // Try to upload immediately
  UploadResult( res.AsJson() );
}