Created
January 13, 2016 17:03
-
-
Save litvil/26b1e2b6bfdbee2055b0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Neighborhood < ActiveRecord::Base | |
has_many :requests, :dependent => :destroy, :foreign_key => 'neighborhood_id', :class_name => "NeighborhoodRequests" | |
before_save :prepare_data | |
MAX_USERS = 30 | |
TYPE_OPEN = 0 | |
TYPE_REQUEST = 1 | |
TYPE_PRIVATE = 2 | |
JOIN_REQUESTS = 'join' | |
INVITE_REQUESTS = 'invite' | |
# params {"emblem":{"icon_image":1,"icon_color":2,"bg_image":3,"bg_color":1,"additional_image":2,"additional_color":3},"level":19,"max_users":30} | |
# user_roles {"6148904":{"role":3,"claims":{},"banned":0},"-fb_12354":{"role":0,"claims":{},"banned":0}} | |
def refresh | |
refresh_avg_level | |
refresh_activity | |
end | |
def refresh_avg_level | |
by_level = {} | |
users_hash.each { |user_id, user_hash| | |
user_hash['level'] | |
by_level[user_hash['level']] ||= 0 | |
by_level[user_hash['level']] += 1 | |
} | |
max = by_level.values.max | |
res = Hash[by_level.select { |k, v| v == max}] | |
self.avg_users_level = if res.size == 1 | |
res.keys.first.to_i | |
else | |
avg = res.keys.sum.to_f / res.keys.size.to_f | |
res.keys.min_by { |x| (x.to_f - avg).abs } | |
end | |
end | |
def emblem | |
@emblem ||= JSON.parse(params || '{}')['emblem'] || {} | |
end | |
def emblem=(val) | |
@emblem = val | |
end | |
def max_users | |
@max_users ||= JSON.parse(params || '{}')['max_users'].to_i | |
end | |
def max_users=(val) | |
@max_users = val | |
end | |
def banned_users | |
return @banned_users unless @banned_users.nil? | |
parsed = JSON.parse(data || '{}')['banned_users'] | |
@banned_users = parsed.present? ? parsed : {} | |
@banned_users | |
end | |
def password | |
@password ||= JSON.parse(params || '{}')['password'].to_s | |
end | |
def secured_password | |
"#{NeighborhoodController.config['secret_room_key']}#{password}" | |
end | |
def password=(val) | |
@password = val | |
end | |
def users_hash | |
@users_hash ||= user_roles.present? ? JSON.parse(user_roles) : {} | |
end | |
def users_hash=(new_users) | |
@users_hash = new_users | |
end | |
def join_requests | |
requests.joins.map{|req| req.user_id} | |
end | |
def join_requests_obj | |
Hash[requests.joins.map{|req| [req.user_id.to_s, req.created_at.to_i]}] | |
end | |
def invite_requests | |
requests.invites.map{|req| req.user_id} | |
end | |
def invite_requests_obj | |
Hash[requests.invites.map{|req| [req.user_id.to_s, req.created_at.to_i]}] | |
end | |
def prepare_data | |
my_params = {} | |
my_params['emblem'] = emblem | |
my_params['password'] = password | |
my_params['max_users'] = max_users if max_users > 0 | |
self.params = my_params.to_json | |
my_data = {} | |
my_data['banned_users'] = banned_users | |
self.data = my_data.to_json | |
self.user_roles = users_hash.to_json if @users_hash.present? | |
unless name.present? | |
self.name = Base64.strict_encode64(Locale.get_translate(NeighborhoodController.config['neighborhood_default_name'], nil, Translation.current_locale)) | |
end | |
end | |
def change_role(user_id, new_role) | |
check_member(user_id) | |
role = get_role_by_user_id(user_id) | |
return false if new_role == role | |
set_role(user_id, new_role.to_i) | |
end | |
def check_member(user_id) | |
raise DZError.new('not a member of neighborhood') unless member?(user_id) | |
end | |
def add_user(user, role) | |
raise DZError.new('user is already in the neighborhood') if users_hash.keys.include?(user.user_id) | |
@users_hash[user.user_id] = {'role' => -1, 'claims' => {}, 'banned' => 0, 'level' =>user.level} | |
set_role(user.user_id, role.to_i) | |
set_level(user.user_id, user.level) | |
refresh_activity | |
refresh_invites | |
restore_ban(user.user_id) | |
end | |
def remove_user(user_id) | |
cache_ban(user_id) | |
@users_hash.delete(user_id) | |
refresh_avg_level | |
refresh_activity | |
end | |
def cache_ban(user_id) | |
if user_banned?(user_id) | |
banned_users[user_id] = users_hash[user_id]['banned'].to_i | |
end | |
end | |
def restore_ban(user_id) | |
time = banned_users[user_id].to_i | |
if time > 0 | |
if time >= Server.current_time.to_i | |
ban_member(user_id, time) | |
else | |
banned_users.delete(user_id) | |
end | |
end | |
end | |
def refresh_activity | |
self.activity = (( (max_users.to_f/2.0) - members_count.to_f).abs*100).round | |
end | |
def refresh_invites | |
remove_all_invite_requests if full? | |
end | |
def add_join_request(user_id) | |
requests.joins.for_user(user_id).create! | |
end | |
def add_invite_request(user_id) | |
requests.invites.for_user(user_id).create! | |
end | |
def remove_invite_request(user_id) | |
invites_for_user = requests.invites.for_user(user_id) | |
return unless invites_for_user.size > 0 | |
invites_for_user.first.destroy | |
end | |
def remove_join_request(user_id) | |
requests_joins_for_user = requests.joins.for_user(user_id) | |
return unless requests_joins_for_user.size > 0 | |
requests_joins_for_user.first.destroy | |
end | |
def remove_all_join_requests | |
requests.joins.destroy_all | |
end | |
def remove_all_invite_requests | |
requests.invites.destroy_all | |
end | |
def remove_all_requests | |
requests.destroy_all | |
end | |
def set_role(user_id, role) | |
current_count = members_count_by_roles([role]) | |
check_member(user_id) | |
raise DZError.new("too many users for role #{role}", "users_count = #{current_count}") if current_count >= NeighborhoodController.config['roles'][role]['max_count'] | |
@users_hash[user_id]['role'] = role | |
end | |
def set_level(user_id, level) | |
check_member(user_id) | |
@users_hash[user_id]['level'] = level.to_i | |
refresh_avg_level | |
end | |
def get_role_by_user_id(user_id) | |
member?(user_id) ? users_hash[user_id]['role'] : -1 | |
end | |
def get_first_user_by_role(role) | |
users_hash.each{|user_id, member| | |
return user_id if member['role'] == role | |
} | |
nil | |
end | |
def leader_id | |
get_first_user_by_role(NeighborhoodMemberRole::ROLE_CREATOR) | |
end | |
def get_all_user_by_role(role) | |
res = [] | |
users_hash.each{|user_id, member| | |
res.push(user_id) if member['role'] == role | |
} | |
res | |
end | |
def can_delete? | |
users_hash.present? && members_count <= 1 | |
end | |
def has_user_join_request?(user_id) | |
requests.joins.for_user(user_id).size > 0 | |
end | |
def has_user_invite_request?(user_id) | |
requests.invites.for_user(user_id).size > 0 | |
end | |
def members_count | |
users_hash.size | |
end | |
def members_count_by_roles(roles) | |
members_by_roles(roles).size | |
end | |
def members_by_roles(roles_array) | |
users_hash.select { |id, member| roles_array.include?(member['role']) } | |
end | |
def type_open? | |
neighborhood_type == TYPE_OPEN | |
end | |
def type_request? | |
neighborhood_type == TYPE_REQUEST | |
end | |
def type_private? | |
neighborhood_type == TYPE_PRIVATE | |
end | |
def symbol_type | |
case neighborhood_type | |
when TYPE_OPEN | |
return :type_open | |
when TYPE_PRIVATE | |
return :type_private | |
when TYPE_REQUEST | |
return :type_request | |
else | |
nil | |
end | |
end | |
def has_free_space? | |
members_count < max_users | |
end | |
def free_space_count | |
max_users - members_count | |
end | |
def full? | |
!has_free_space? | |
end | |
def member?(user_id) | |
users_hash.has_key?(user_id) | |
end | |
def has_role?(user_id, role) | |
users_hash[user_id].present? && users_hash[user_id]['role'] == role | |
end | |
def ban_member(user_id, time) | |
check_member(user_id) | |
users_hash[user_id]['banned'] = time.to_i | |
users_hash[user_id]['claims'] = {} | |
end | |
def unban_member(user_id) | |
check_member(user_id) | |
users_hash[user_id]['banned'] = 0 | |
users_hash[user_id]['claims'] = {} | |
end | |
def user_banned?(user_id) | |
users_hash[user_id].present? && users_hash[user_id]['banned'].to_i >= Server.current_time.to_i | |
end | |
def has_claim?(sad_user_id, target_user_id) | |
users_hash[target_user_id].present? && users_hash[target_user_id]['claims'].has_key?(sad_user_id) | |
end | |
def add_claim(sad_user_id, target_user_id) | |
@users_hash[target_user_id]['claims'][sad_user_id] = Server.current_time.to_i | |
end | |
def delete_claim(sad_user_id, target_user_id) | |
@users_hash[target_user_id]['claims'].delete(sad_user_id) | |
end | |
def claims_count(target_user_id) | |
users_hash[target_user_id]['claims'].size rescue 0 | |
end | |
def server_config | |
{ | |
'active' => Chat::SFS_CONFIG['chat_active'][shard_number], | |
'host' => Chat::SFS_CONFIG['chat_address'][shard_number], | |
'zone' => Chat::SFS_CONFIG['chat_zone'][shard_number] | |
} | |
end | |
def shard_number | |
Chat.get_shard_number(id) | |
end | |
def to_client | |
{ | |
'id' => id, | |
'name' => Base64.strict_encode64(name), | |
'descr' => description, | |
'emblem' => emblem, | |
'level' => level || NeighborhoodController.config['min_level'], | |
'max_users' => max_users, | |
'users' => users_hash, | |
'lang' => lang, | |
'avg_users_level' => avg_users_level, | |
'type' => neighborhood_type | |
} | |
end | |
def my_to_client | |
{ | |
'id' => id, | |
'name' => Base64.strict_encode64(name), | |
'descr' => description, | |
'emblem' => emblem, | |
'level' => level || NeighborhoodController.config['min_level'], | |
'max_users' => max_users, | |
'server_config' => server_config, | |
'password' => password, | |
'users' => users_hash, | |
'type' => neighborhood_type, | |
'avg_users_level' => avg_users_level, | |
'activity' => activity, | |
'lang' => lang, | |
'joins' => join_requests_obj, | |
'invites' => invite_requests_obj | |
} | |
end | |
def self.from_hash(hash) | |
hood = Neighborhood.new | |
hash.each{|key, val| | |
hood[key]=val if hood.respond_to?(key.to_sym) | |
} | |
hood | |
end | |
end | |
class NeighborhoodRequests < ActiveRecord::Base | |
INVITE_TYPE = 0 | |
JOIN_TYPE = 1 | |
belongs_to :neighborhood | |
named_scope :for_user, lambda { |user_id| { :conditions => { :user_id => user_id.to_s } } } | |
named_scope :invites, {:conditions => {:request_type => INVITE_TYPE}, :order =>'created_at ASC'} | |
named_scope :joins, {:conditions => {:request_type => JOIN_TYPE}, :order =>'created_at ASC'} | |
named_scope :for_neighborhood, lambda { |hood_id| { :conditions => { :neighborhood_id => hood_id.to_i } } } | |
named_scope :for_neighborhoods, lambda { |hood_ids| { :conditions => { :neighborhood_id => hood_ids } } } | |
named_scope :for_users, lambda { |user_ids| { :conditions => { :user_id => user_ids } } } | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment