Skip to content

Instantly share code, notes, and snippets.

@kmlawson
Created July 16, 2012 21:34
Show Gist options
  • Save kmlawson/3125223 to your computer and use it in GitHub Desktop.
Save kmlawson/3125223 to your computer and use it in GitHub Desktop.
This open source script is for Mac OS X or Linux, with Ruby installed. You can run the script via the command line with "ruby anki1.0.rb" for example. This version of the script is very simple: it extracts certain statistics from your Anki decks (edit the
(*
Copyright 2009 Konrad M. Lawson
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
#Modification of code provided by arnebrasseur
require 'date'
#An array of the flashcard files you want to read stats from:
decks = ['/path/to/your/deck.anki','/path/to/a/second/deck/if/you/have/one.anki']
#The name of the location where you want to save the stats to:
statsdir = '/path/to/the/directory/where/you/will/save/the/log/file/'
#If true this will prevent more than one log entry being made per day:
$onceperday = true
if !File.directory? statsdir
exit
end
class AnkiStats
attr_reader :path,:name,:due,:unseen,:facts,:cards,:todayCount,:todayTime,:yCount,:yTime,:lastDate,:lastCount,:lastTime,:daysSince
def zeroit(checkvar)
if checkvar==nil
checkvar=0
end
return checkvar
end
def convertMin(secondz)
if secondz.to_i>0
secondz=secondz.to_f/60
rounded=secondz.round.to_s
end
end
#Get the raw data from the decks, initialize the variables
def initialize(deckPath)
@path = deckPath
@today = Time.now.strftime("%Y-%m-%d")
@yesterday = (Time.now-86400).strftime("%Y-%m-%d")
@daysSince = 0
@unseen = 0
@due = 0
@todayCount = 0
@todayTime = 0
@lastDate = ""
@cards = 0
@facts = 0
deckstats = `sqlite3 '#{@path}' 'select syncName,revCount,newCount,factCount,cardCount from decks;'`
deckstatsArray=deckstats.split("|")
#Should probably do some error checking here to see if got necessary data
daystats=`sqlite3 -list '#{@path}' 'select day,reps,reviewTime from stats;'`
#Should probably do some error checking on this too.
getstats(daystats)
@name = File.basename(path,File.extname(path))
@due=zeroit(deckstatsArray[1])
@unseen=zeroit(deckstatsArray[2])
@facts=zeroit(deckstatsArray[3])
@cards=deckstatsArray[4]
if @cards==nil
@cards=0
else
@cards=@cards.strip
end
end
#Assign the appropriate data to each variable
def getstats(daystats)
daystatsArray=daystats.split("\n").reverse
for myentry in 0 ... daystatsArray.length-1
mydata=daystatsArray[myentry].split('|')
if mydata[0]==@today
if mydata[1].to_i>0
@todayCount=mydata[1]
else
@todayCount=0
end
if mydata[2].to_i>0
@todayTime=convertMin(mydata[2])
else
@todayTime=0
end
elsif mydata[0]==@yesterday
@yCount=mydata[1]
@yTime=convertMin(mydata[2])
break
else
if todayCount==nil||todayCount.to_i<1
@lastDate=mydata[0]
@lastCount=mydata[1]
if @lastCount==nil
@lastCount=0
end
@lastTime=convertMin(mydata[2])
@daysSince=Date.today-Date.strptime(lastDate)
if @daysSince==nil
@daysSince=0
end
break
end
end
end
end
end
#For each file name that is passed, create an AnkiStats, and write its data to a file by the name of the deck in the target directory
#If there is already an entry for today (when a log of the stats were saved, not last time deck was studied) don't write a new log entry, unless $onceperday is false
#If the target file does not already exist, create it and add headers to show what the data is for.
def writeStats(readFile,statsdir)
if !File.exist?(readFile)
puts "File not found: "+readFile
exit
end
a=AnkiStats.new(readFile)
writeFile=statsdir+a.name+".txt"
if !File.exist?(writeFile)
Dir.chdir(statsdir)
f=File.new(a.name+".txt","a")
f.puts "Log Date\tUnseen\tDue\tCards Studied\tTime Studied\tTotal Cards\tTotal Facts\tDays Since Last Study\tLast Session"
f.close
end
if a.unseen==nil
@daysSince=0
end
if $onceperday
#Find out the date of the last log entry and only write a new log entry if one hasn't been made today:
lastLine = `tail -n 1 '#{writeFile}'`
lastLine=lastLine.split("\t")
else
#If the user has disabled this, make it so that the if statement below will always pass
lastLine=0
end
if lastLine[0]!=Time.now.strftime("%Y.%m.%d")
open(writeFile,'a') do |x|
x.puts Time.now.strftime("%Y.%m.%d")+"\t"+a.unseen.to_s+"\t"+a.due.to_s+"\t"+a.todayCount.to_s+"\t"+a.todayTime.to_s+"\t"+a.cards.to_s+"\t"+a.facts.to_s+"\t"+a.daysSince.to_s+"\t"+a.lastDate.gsub("-",".")
end
end
end
decks.each { |theFile|
writeStats(theFile,statsdir)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment