How to Add :committed Days to :levels?
Assuming committed is a field containing an array of day names (e.g. ['Monday', 'Friday']
, the following should work:
committed_wdays = committed..map { |day| Date::DAYNAMES.index(day) }
n_days = (date_started..Date.today).count { |date| committed_wdays.include? date.wday }
How to restart current_level for every third missed_day (3 strikes you're out!)?
Here is my solution:
You need to keep track the days you lost at the moment you get 3 missed days (you need to add a field in level):
migration file.rb
class AddDaysLostToLevels < ActiveRecord::Migration
def change
add_column :levels, :days_lost, :integer, default: 0
end
end
Then change controller days_missed to reset when you get 3 missed days and store the days you lost when you start again level (in the variable 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
Now we need to define "calculate_days_lost" and "real_missed_days" methods in habit.rb.
Remember to use self.real_missed_days instead self.missed_days in current_level method: (they are diferent because you can start again a level). New habit.rb will be like this:
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
How do I make a Git commit in the past?
The advice you were given is flawed. Unconditionally setting GIT_AUTHOR_DATE in an --env-filter
would rewrite the date of every commit. Also, it would be unusual to use git commit inside --index-filter
.
You are dealing with multiple, independent problems here.
Specifying Dates Other Than “now”
Each commit has two dates: the author date and the committer date. You can override each by supplying values through the environment variables GIT_AUTHOR_DATE and GIT_COMMITTER_DATE for any command that writes a new commit. See “Date Formats” in git-commit(1) or the below:
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
The only command that writes a new commit during normal use is git commit. It also has a --date
option that lets you directly specify the author date. Your anticipated usage includes git filter-branch --env-filter
also uses the environment variables mentioned above (these are part of the “env” after which the option is named; see “Options” in git-filter-branch(1) and the underlying “plumbing” command git-commit-tree(1).
Inserting a File Into a Single ref History
If your repository is very simple (i.e. you only have a single branch, no tags), then you can probably use git rebase to do the work.
In the following commands, use the object name (SHA-1 hash) of the commit instead of “A”.
Do not forget to use one of the “date override” methods when you run git commit.
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o master
If you wanted to update A to include the new file (instead of creating a new commit where it was added), then use git commit --amend
instead of git commit
. The result would look like this:
---A'---B'---C'---o---o---o master
The above works as long as you can name the commit that should be the parent of your new commit. If you actually want your new file to be added via a new root commit (no parents), then you need something a bit different:
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
\
B'---C'---o---o---o master
git checkout --orphan
is relatively new (Git 1.7.2), but there are other ways of doing the same thing that work on older versions of Git.
Inserting a File Into a Multi-ref History
If your repository is more complex (i.e. it has more than one ref (branches, tags, etc.)), then you will probably need to use git filter-branch. Before using git filter-branch, you should make a backup copy of your entire repository. A simple tar archive of your entire working tree (including the .git directory) is sufficient. git filter-branch does make backup refs, but it is often easier to recover from a not-quite-right filtering by just deleting your .git
directory and restoring it from your backup.
Note: The examples below use the lower-level command git update-index --add
instead of git add
. You could use git add, but you would first need to copy the file from some external location to the expected path (--index-filter
runs its command in a temporary GIT_WORK_TREE that is empty).
If you want your new file to be added to every existing commit, then you can do this:
new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard
I do not really see any reason to change the dates of the existing commits with --env-filter 'GIT_AUTHOR_DATE=…'
. If you did use it, you would have make it conditional so that it would rewrite the date for every commit.
If you want your new file to appear only in the commits after some existing commit (“A”), then you can do this:
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
If you want the file to be added via a new commit that is to be inserted into the middle of your history, then you will need to generate the new commit prior to using git filter-branch and add --parent-filter
to git filter-branch:
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
You could also arrange for the file to be first added in a new root commit: create your new root commit via the “orphan” method from the git rebase section (capture it in new_commit
), use the unconditional --index-filter
, and a --parent-filter
like "sed -e \"s/^$/-p $new_commit/\""
.
undefined method `each_with_index' for 0:Fixnum
When you try to load the new
template you are getting this error because @habit.levels
is returning 0
rather than an enumerable object. Since you can't iterate over a Fixnum
, the exception is being thrown when it gets to the .each_with_index
call. Check out this line in your code:
def levels
return 0 unless date_started
...
end
It looks like you're validating the presence of date_started
but with this @habit
the #levels
method is returning 0
.
As ilan berci points out, this line is always going to fail when chained with .each_with_index
because it is named levels
but returns a Fixnum
. Looking back at the top of your model, however, you've already declared has many :levels
up there, which generates its own levels
method that will gather all the levels associated with the given @habit
and return them as an enumerable object .
It sounds like that's what you were expecting to happen based on the use of each_with_index
, but when you declared the other levels
method further down in the model, it overrides the method given to you by the has_many :levels
line. If you really do need to iterate over a collection of a habit's levels, you should change the name of the custom levels
method that is now designed to return a Fixnum
based on the value of n_days
.
Creating a Calculated Time Periods Hierarchy
I've just created the same this way:
1) Add dummy attribute for unfiltered values with the name 'All Time'
(key is int with 0 value)
2) Add 3 empty members
CREATE MEMBER CURRENTCUBE.[Report Date].[Time Period].[All].[Last 30 Days]
AS
null,
VISIBLE = 1;
CREATE MEMBER CURRENTCUBE.[Report Date].[Time Period].[All].[Last 60 Days]
AS
null,
VISIBLE = 1;
CREATE MEMBER CURRENTCUBE.[Report Date].[Time Period].[All].[Last 90 Days]
AS
null,
VISIBLE = 1;
3) Than add scopes (I have another key format):
/* SCOPES */
SCOPE ([Report Date].[Time Period].[All].[Last 30 Days]);
THIS = Sum(LastPeriods(30,StrToMember("[Report Date].[Report Date].[Day].&["+CStr(Format(Now(),"yyyyMMdd"))+"]")));
END SCOPE;
SCOPE ([Report Date].[Time Period].[All].[Last 60 Days]);
THIS = Sum(LastPeriods(60,StrToMember("[Report Date].[Report Date].[Day].&["+CStr(Format(Now(),"yyyyMMdd"))+"]")));
END SCOPE;
SCOPE ([Report Date].[Time Period].[All].[Last 90 Days]);
THIS = Sum(LastPeriods(90,StrToMember("[Report Date].[Report Date].[Day].&["+CStr(Format(Now(),"yyyyMMdd"))+"]")));
END SCOPE;
It works (also add a measure to count members of a level to validate):
How can i change the position of the days(number) in tkcalendar
There is no option to change the position of the day numbers. Therefore, it is necessary to dig into the source code of the widget to do it. The days are just labels so it is possible get the desired position by setting their anchor
option to "nw"
. They are stored into a list of lists called ._calendar
(one list per week):
import tkinter as tk
from tkcalendar import Calendar
class MyCalendar(Calendar):
def __init__(self, master, **kw):
Calendar.__init__(self, master, **kw)
for row in self._calendar:
for label in row:
label['anchor'] = "nw"
# # uncomment this block to align left weekday names
# for label in self._week_days:
# label['anchor'] = "w"
root = tk.Tk()
cal = MyCalendar(root, showweeknumbers=False)
cal.pack(fill='both', expand=True)
root.geometry("400x300")
root.mainloop()
git revert back to certain commit
git reset --hard 4a155e5
Will move the HEAD back to where you want to be. There may be other references ahead of that time that you would need to remove if you don't want anything to point to the history you just deleted.
Related Topics
Factory Girl - What's the Purpose
Attr_Accessor on Class Variables
Rails If Object.Nil? Then Magic '' in Views
Reraise (Same Exception) After Catching an Exception in Ruby
What Is the Meaning of "H" in "<%=H [ ...] %>"
Rails: Money Gem Converts All Amounts to Zero
Cannot Click HTML Element with Watir
Method_Missing Gotchas in Ruby
Ruby: Is There an Opposite of Include? for Ruby Arrays
Raise Custom Exception with Arguments
Are There Any Ipython-Like Shells for Ruby or Rails
Converting Utc Timestamp to Iso 8601 in Ruby