如何每三次 missed_day 重新启动 current_level(3 次罢工!)?
How to restart current_level for every third missed_day (3 strikes you're out!)?
例如,如果用户处于第 4 级:第 50 天,他将被推回第 45 天。
case n_days
when 0..9 # Would go back to 0
1
when 10..24 # Back to 10
2
when 25..44 # Back to 25
3
when 45..69 # Back to 45
4
when 70..99 # Back to 70
5
else
"Mastery"
end
然后假设他再次返回,这次是第 68 天,如果他再次检查 3 missed_days
,他将再次被推回到第 45 天:
_form(以上图片为代表):
<label id="<%= @habit.id %>" class="habit-id"> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
<p>
<label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label>
<%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %>
</p>
<% end %>
habit.rb
class Habit < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
has_many :levels
serialize :committed, Array
validates :date_started, presence: true
before_save :current_level
acts_as_taggable
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
attr_accessor :missed_one, :missed_two, :missed_three
def save_with_current_level
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def current_level_strike
levels[current_level - 1] # remember arrays indexes start at 0
end
def current_level
return 0 unless date_started
def committed_wdays
committed.map do |day|
Date::DAYNAMES.index(day.titleize)
end
end
def n_days
((date_started.to_date)..Date.today).count do |date|
committed_wdays.include? date.wday
end - self.missed_days
end
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
6
end
end
end
habit.js
$(document).ready(function() {
var handleChange = function() {
habit = $(this).parent().prev().attr("id");
level = $('label', $(this).parent()).attr("id");
if ($(this).is(":checked")) {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed",
method: "POST"
});
} else {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
method: "DELETE"
});
}
if (!$('input[type="checkbox"]:not(:checked)', $(this).parent()).length) {
/* this is just an example, you will have to ammend this */
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(".habit-check").on('change',handleChange);
}
}
$(".habit-check").on('change',handleChange);
});
days_missed_controller.rb
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days - 1
habit.save
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
这是要点:https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2
如果您还需要代码、解释或图片,请告诉我:)
如果我理解正确的话,您在这里要实现的目标是期望用户在几天内每天都做某事。如果他在给定的 "level period" 中没有这样做 3 次,你想重置他的 "level progress",对吗?
如果是这样,最简单的解决方案是添加另一个变量,例如:days_lost
.
然后,你可以在habit.rb中应用它:
n_days = ((date_started.to_date)..Date.today).count { |date| committed_wdays.include? date.wday } - self.missed_days - self.days_lost
记得每次用户 "misses" 3 次更新它,在 days_missed_controller.rb:
中看起来像这样
def create
...
if missed_days == 3
missed_days = 0
days_lost = <days from beginning of the level>
end
...
end
更新:
<days from beginning of the level>
可以通过创建另一个辅助变量来计算,例如pending_days
并给它一个起始值 0
。每一天,pending_days += 1
.
接下来我们要案例:
1:玩家 "misses" 3 天达到当前级别 - 我们将从级别开始的天数添加到负(丢失)天数,然后重新开始计数
days_lost += pending_days
pending_days = 0
2:玩家 "misses" 少于 3 天 - 我们只是提高他的等级,然后重新开始计数,因为他处于新等级
pending_days = 0
这是我的解决方案:
您需要在错过 3 天的那一刻跟踪您失去的天数(您需要在级别中添加一个字段):
迁移file.rb
class AddDaysLostToLevels < ActiveRecord::Migration
def change
add_column :levels, :days_lost, :integer, default: 0
end
结束
然后更改控制器 days_missed 以在错过 3 天时重置并在重新开始时存储丢失的天数(在变量 days_lost 中):
class DaysMissedController < ApplicationController
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
if level.missed_days == 3
level.missed_days = 0
level.days_lost += habit.calculate_days_lost + 1
end
...remain the same
现在我们需要在habit.rb中定义"calculate_days_lost"和"real_missed_days"方法。
记得在current_level方法中使用self.real_missed_days代替self.missed_days:(它们是不同的,因为你可以重新开始一个级别)。新的habit.rb会是这样的:
class Habit < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
has_many :levels
serialize :committed, Array
validates :date_started, presence: true
before_save :current_level
acts_as_taggable
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
attr_accessor :missed_one, :missed_two, :missed_three
def save_with_current_level
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def current_level_strike
levels[current_level - 1] # remember arrays indexes start at 0
end
def real_missed_days
value = 0
levels.each do |level|
if level.missed_days != nil
value += level.missed_days + level.days_lost
end
end
value
end
def committed_wdays
committed.map do |day|
Date::DAYNAMES.index(day.titleize)
end
end
def n_days
((date_started.to_date)..Date.today).count do |date|
committed_wdays.include? date.wday
end - self.real_missed_days
end
def calculate_days_lost
case n_days
when 0..9
n_days
when 10..24
n_days-10
when 25..44
n_days-25
when 45..69
n_days-45
when 70..99
n_days-70
else
n_days-100
end
end
def current_level
return 0 unless date_started
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
6
end
end
end
例如,如果用户处于第 4 级:第 50 天,他将被推回第 45 天。
case n_days
when 0..9 # Would go back to 0
1
when 10..24 # Back to 10
2
when 25..44 # Back to 25
3
when 45..69 # Back to 45
4
when 70..99 # Back to 70
5
else
"Mastery"
end
然后假设他再次返回,这次是第 68 天,如果他再次检查 3 missed_days
,他将再次被推回到第 45 天:
_form(以上图片为代表):
<label id="<%= @habit.id %>" class="habit-id"> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
<p>
<label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label>
<%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %>
</p>
<% end %>
habit.rb
class Habit < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
has_many :levels
serialize :committed, Array
validates :date_started, presence: true
before_save :current_level
acts_as_taggable
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
attr_accessor :missed_one, :missed_two, :missed_three
def save_with_current_level
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def current_level_strike
levels[current_level - 1] # remember arrays indexes start at 0
end
def current_level
return 0 unless date_started
def committed_wdays
committed.map do |day|
Date::DAYNAMES.index(day.titleize)
end
end
def n_days
((date_started.to_date)..Date.today).count do |date|
committed_wdays.include? date.wday
end - self.missed_days
end
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
6
end
end
end
habit.js
$(document).ready(function() {
var handleChange = function() {
habit = $(this).parent().prev().attr("id");
level = $('label', $(this).parent()).attr("id");
if ($(this).is(":checked")) {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed",
method: "POST"
});
} else {
$.ajax({
url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
method: "DELETE"
});
}
if (!$('input[type="checkbox"]:not(:checked)', $(this).parent()).length) {
/* this is just an example, you will have to ammend this */
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(this).parent().append($('<input type="checkbox" class="habit-check">'));
$(".habit-check").on('change',handleChange);
}
}
$(".habit-check").on('change',handleChange);
});
days_missed_controller.rb
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days - 1
habit.save
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
这是要点:https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2
如果您还需要代码、解释或图片,请告诉我:)
如果我理解正确的话,您在这里要实现的目标是期望用户在几天内每天都做某事。如果他在给定的 "level period" 中没有这样做 3 次,你想重置他的 "level progress",对吗?
如果是这样,最简单的解决方案是添加另一个变量,例如:days_lost
.
然后,你可以在habit.rb中应用它:
n_days = ((date_started.to_date)..Date.today).count { |date| committed_wdays.include? date.wday } - self.missed_days - self.days_lost
记得每次用户 "misses" 3 次更新它,在 days_missed_controller.rb:
中看起来像这样def create
...
if missed_days == 3
missed_days = 0
days_lost = <days from beginning of the level>
end
...
end
更新:
<days from beginning of the level>
可以通过创建另一个辅助变量来计算,例如pending_days
并给它一个起始值 0
。每一天,pending_days += 1
.
接下来我们要案例:
1:玩家 "misses" 3 天达到当前级别 - 我们将从级别开始的天数添加到负(丢失)天数,然后重新开始计数
days_lost += pending_days
pending_days = 0
2:玩家 "misses" 少于 3 天 - 我们只是提高他的等级,然后重新开始计数,因为他处于新等级
pending_days = 0
这是我的解决方案:
您需要在错过 3 天的那一刻跟踪您失去的天数(您需要在级别中添加一个字段):
迁移file.rb
class AddDaysLostToLevels < ActiveRecord::Migration
def change
add_column :levels, :days_lost, :integer, default: 0
end
结束
然后更改控制器 days_missed 以在错过 3 天时重置并在重新开始时存储丢失的天数(在变量 days_lost 中):
class DaysMissedController < ApplicationController
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
if level.missed_days == 3
level.missed_days = 0
level.days_lost += habit.calculate_days_lost + 1
end
...remain the same
现在我们需要在habit.rb中定义"calculate_days_lost"和"real_missed_days"方法。
记得在current_level方法中使用self.real_missed_days代替self.missed_days:(它们是不同的,因为你可以重新开始一个级别)。新的habit.rb会是这样的:
class Habit < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
has_many :levels
serialize :committed, Array
validates :date_started, presence: true
before_save :current_level
acts_as_taggable
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
attr_accessor :missed_one, :missed_two, :missed_three
def save_with_current_level
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def current_level_strike
levels[current_level - 1] # remember arrays indexes start at 0
end
def real_missed_days
value = 0
levels.each do |level|
if level.missed_days != nil
value += level.missed_days + level.days_lost
end
end
value
end
def committed_wdays
committed.map do |day|
Date::DAYNAMES.index(day.titleize)
end
end
def n_days
((date_started.to_date)..Date.today).count do |date|
committed_wdays.include? date.wday
end - self.real_missed_days
end
def calculate_days_lost
case n_days
when 0..9
n_days
when 10..24
n_days-10
when 25..44
n_days-25
when 45..69
n_days-45
when 70..99
n_days-70
else
n_days-100
end
end
def current_level
return 0 unless date_started
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
6
end
end
end