## 数据库字段说明
# status 0:已开启;1:正在评测;2:通过评测;3:锁定
# modify_time: 与challenges表的modify_time联合使用,2个字段一致,则标识测试集未修改,反之,被修改
# answer_open: 查看查看答案的深度, 0: 未查看过答案, 其他数值与challenge_answer的level值相关
# answer_deduction: 查看答案扣分的百分比;如 查看答案 扣除70%
#play_sign 与play_time: sign记录浏览器是否正常关闭, 0表示正常,1表示非正常; play_time:表示游玩时间
class Game < ApplicationRecord
  default_scope { order("games.created_at desc") }

  #TODO: games表要增加challenge_id与user_id的唯一索引
  has_many :outputs, -> { order('query_index DESC') }
  has_many :challenge_samples, :dependent => :destroy
  has_many :game_codes, :dependent => :destroy
  has_many :evaluate_records, -> { order('id DESC') }, :dependent => :destroy
  belongs_to :myshixun
  belongs_to :user
  belongs_to :challenge
  has_one :run_code_message, :dependent => :destroy
  has_many :game_answers, :dependent => :destroy

  #全部关卡数
  scope :ch_games, lambda { |challenge_id| where(challenge_id:challenge_id) }
  # 已通关的数量
  scope :finished_num, -> (challenge_id) { where(:challenge_id => challenge_id, :status => 2)}
  # 正在通关的数量
  scope :doing_num, -> (challenge_id) { where(:challenge_id => challenge_id, :status => [0,1])}

  #用户的全部关卡
  scope :user_games, lambda { |user_id,challenge_id| where("user_id = ? AND challenge_id = ?",user_id,challenge_id) }

  validates :identifier, uniqueness: true

  # 服务器uri+port的redis的key
  def server_key
    "game_server_url_#{id}"
  end

  def set_server_key(server_url)
    Rails.cache.write("#{server_key}", server_url, expires_in: 5.minute)
  end

  def get_server_url
    Rails.cache.read(server_key)
  end

  # 根据得分比例来算实际得分(试卷、实训作业)
  def real_score score
    ((final_score < 0 ? 0 : final_score).to_f / challenge.score) * score
  end

  # 判断实训是否全部通关
  def had_done
    Game.where(myshixun: self.myshixun_id).where("status != 2").count > 0 ? 0 : 1
  end

  def owner
    self.user
  end

  def had_passed?
    self.status == 2
  end

  # 因为outputs是按qurey_index倒序,所有first取的qurey_index的最大值
  # 之所以加1是因为,存的时候要递增,如果仅取的话,则注意:必须减一
  def query_index
    # Output.unscope(:order).maximum("query_index").where(game_id: self.id)
    self.outputs.unscope(:order).maximum("query_index")
  end

  # 用户在game关卡中获得的金币和经验值
  # st: 0 实战类型;1 选择题类型
  def user_get_gold_and_experience shixun_status, challenge
    if challenge.st == 0 # 实战类型
      if self.status == 2  # 通关了则取实际得分,没通关则取总分
        gold = (shixun_status <= 1) ? 0 : self.final_score.to_i
        # 只要过关了,查看了答案经验值就是0;通关前查看了答案金final_score为负数
        experience = (shixun_status <= 1 || self.final_score.to_i < 0) ? 0 : self.final_score.to_i
      else
        gold = challenge.score.to_i
        experience = gold
      end
    else
      if self.status == 2
        gold = (shixun_status <= 1) ? 0 : self.final_score.to_i
        experience = (shixun_status <= 1 || self.final_score.to_i < 0) ? 0 : challenge.choose_score.to_i
      else
        # 选择题只有在全对的时候才会获取final score总分,错任何一个题final_score就为0
        gold = challenge.choose_score
        experience = challenge.choose_score
      end
    end
    [gold, experience]
  end

  # 上一关
  def prev_of_current_game shixun_id, myshixun_id, challenge_position
    Game.find_by_sql("select identifier from games where myshixun_id=#{myshixun_id}
                      and challenge_id=(select id from challenges where shixun_id=#{shixun_id} and
                      position=#{challenge_position - 1})").first.try(:identifier)
  end

  # 下一关
  def next_of_current_game shixun_id, myshixun_id, challenge_position
    Game.find_by_sql("select * from games where myshixun_id=#{myshixun_id}
                      and challenge_id=(select id from challenges where shixun_id=#{shixun_id} and
                      position=#{challenge_position + 1})").first.try(:identifier)
  end

  # 针对api形式取下一关identifier
  def next_game shixun_id, myshixun_id, challenge_position
    Game.find_by_sql("select * from games where myshixun_id=#{myshixun_id}
                      and challenge_id=(select id from challenges where shixun_id=#{shixun_id} and
                      position=#{challenge_position + 1})").first
  end

  # 因为outputs是按qurey_index倒序,所有first取的qurey_index的最大值
  # 之所以加1是以为,存的时候要递增,如果仅取的话,则注意:必须减一
  def next_query_index
    if self.outputs.try(:first).present?
      self.outputs.first.try(:query_index).to_i + 1
    else
      1
    end
  end

  def choose_correct_num query_index
    self.outputs.where(query_index: query_index, result: 1).count
  end

  # 评测次数
  #def evaluate_count
  #  self.outputs.pluck(:query_index).first
  #end

  # 是否查看了答案(通关的是否在通关前看的答案)
  def view_answer
    answer_exists = Grade.where("container_type = 'Answer' and container_id = #{self.id} and created_at < '#{self.end_time}'").exists?
    answer_open != 0 ? (status == 2 ? answer_exists : true) : false
  end

  # 用户关卡得分
  def get_user_final_score

  end

  # 按评测次数的查询
  def distinct_query_index
    self.outputs.group("outputs.query_index").reorder("query_index asc")
  end

  def lastest_code
    self.game_codes.first.try(:new_code)
    # game_code = GameCode.where(:game_id => self.id).first
    # game_code.try(:new_code)
  end
end