|
|
| Line 31: |
Line 31: |
| *Switch to internal oscilator for simplicity and power saving, timing vars need retweaking??? | | *Switch to internal oscilator for simplicity and power saving, timing vars need retweaking??? |
| *Find/make through-hole usb mini eagle part | | *Find/make through-hole usb mini eagle part |
|
| |
| -- This module is a replacement for the RfX report bot.
| |
|
| |
| local rfx = require( 'Module:Rfx' )
| |
| local colours = mw.loadData( 'Module:RFX report/colour' )
| |
|
| |
| local p = {}
| |
|
| |
| local function getTableLength(tbl)
| |
| local length = 0
| |
| for _ in pairs(tbl) do
| |
| length = length + 1
| |
| end
| |
| return length
| |
| end
| |
|
| |
| local function getRfxes()
| |
| -- Get the title object for [[Wikipedia:Requests for adminship]].
| |
| local noError, rfa = pcall( mw.title.new, 'Wikipedia:Requests for adminship' )
| |
| if not noError or ( noError and not rfa ) then
| |
| return nil
| |
| end
| |
| local rfaText = rfa:getContent()
| |
| if not rfaText then
| |
| return nil
| |
| end
| |
|
| |
| -- Return a table with a list of pages transcluded from
| |
| -- [[Wikipedia:Requests for adminship]], minus the exceptions
| |
| -- which are always transcluded there.
| |
| local t = {}
| |
| local exceptions = { 'Front matter', 'Header', 'bureaucratship' }
| |
| for rfxPage, rfxSubpage in mw.ustring.gmatch( rfaText, '{{[ _]*([wW]ikipedia:[rR]equests for %w+/([^{}]-))[ _]*}}' ) do
| |
| local isException = false
| |
| for _, v in ipairs( exceptions ) do
| |
| if rfxSubpage == v then
| |
| isException = true
| |
| end
| |
| end
| |
| if not isException then
| |
| table.insert( t, rfxPage )
| |
| end
| |
| end
| |
| return t
| |
| end
| |
|
| |
| local function makeRow( rfxObject )
| |
| if not ( type( rfxObject ) == 'table' and rfxObject.getTitleObject and rfxObject.getSupportUsers ) then
| |
| return nil
| |
| end
| |
| local status = rfxObject:getStatus()
| |
| local page = rfxObject:getTitleObject().prefixedText
| |
| local user = rfxObject.user or rfxObject:getTitleObject().subpageText
| |
| local supports = rfxObject.supports
| |
| local opposes = rfxObject.opposes
| |
| local neutrals = rfxObject.neutrals
| |
| local percent = rfxObject.percent
| |
| local colour
| |
| if percent then
| |
| colour = colours[ rfxObject.type ][ percent ]
| |
| end
| |
| colour = colour or ''
| |
| local votes
| |
| if supports and opposes and neutrals and percent then
| |
| votes = mw.ustring.format( [==[
| |
|
| |
| | class="rfx-report-number" | [[%s#Support|%d]]
| |
| | class="rfx-report-number" | [[%s#Oppose|%d]]
| |
| | class="rfx-report-number" | [[%s#Neutral|%d]]
| |
| | class="rfx-report-number rfx-report-percent" style="background: #%s;" | %d]==],
| |
| page, supports,
| |
| page, opposes,
| |
| page, neutrals,
| |
| colour, percent
| |
| )
| |
| else
| |
| votes = '\n| colspan="4" class="rfx-report-error" | Error parsing votes'
| |
| end
| |
| if status then
| |
| status = mw.language.getContentLanguage():ucfirst( status )
| |
| if status == 'Pending closure' then
| |
| status = 'Pending closure...'
| |
| end
| |
| status = '\n|' .. status
| |
| else
| |
| status = '\n| class="rfx-report-error" | Error getting status'
| |
| end
| |
| local endTime = rfxObject.endTime
| |
| local secondsLeft = rfxObject:getSecondsLeft()
| |
| local timeLeft = rfxObject:getTimeLeft()
| |
| local time
| |
| if endTime and timeLeft then
| |
| time = mw.ustring.format( '\n| %s\n| %s', endTime, timeLeft )
| |
| else
| |
| time = '\n| colspan="2" class="rfx-report-error" | Error parsing end time'
| |
| end
| |
| local dupes = rfxObject:dupesExist()
| |
| if dupes then
| |
| dupes = '<span class="rfx-report-dupes-yes">yes</span>'
| |
| elseif dupes == false then
| |
| dupes = 'no'
| |
| else
| |
| dupes = '--'
| |
| end
| |
| local report = rfxObject:getReport()
| |
| if report then
| |
| report = mw.ustring.format( '\n| [%s report]', tostring( report ) )
| |
| else
| |
| report = '\n| class="rfx-report-error" | Report not found'
| |
| end
| |
| local pending_class = ''
| |
| if status == 'pending closure' then
| |
| pending_class = 'class="rfx-report-pending"'
| |
| end
| |
| return mw.ustring.format(
| |
| '\n|-%s\n| [[%s|%s]]%s%s%s\n| class="rfx-report-dupes" | %s%s',
| |
| pending_class, page, user, votes, status, time, dupes, report
| |
| )
| |
| end
| |
|
| |
| local function makeHeading( rfxType )
| |
| local frame = mw.getCurrentFrame()
| |
| local rfxCaps
| |
| if rfxType == 'rfa' then
| |
| rfxCaps = 'RfA'
| |
| elseif rfxType == 'rfb' then
| |
| rfxCaps = 'RfB'
| |
| else
| |
| return nil
| |
| end
| |
| return mw.ustring.format(
| |
| '\n|-\n! scope="col" | %s candidate !! scope="col" | <abbr title="Support">S</abbr> !! scope="col" | <abbr title="Oppose">O</abbr> !! scope="col" | <abbr title="Neutral">N</abbr> !! scope="col" | <abbr title="Support percentage (%%)">S %%</abbr> !! scope="col" | Status !! scope="col" | Ending (UTC) !! scope="col" | Time left !! scope="col" | <abbr title="Has duplicate votes?">Dups?</abbr> !! scope="col" | Report',
| |
| rfxCaps
| |
| )
| |
| end
| |
|
| |
| local function getRfasRfbsSeparate()
| |
| local rfxes = getRfxes()
| |
| if not rfxes then
| |
| return nil
| |
| end
| |
| -- Get RfX objects and separate RfAs and RfBs.
| |
| local rfas = {}
| |
| local rfbs = {}
| |
| for i, rfxPage in ipairs( rfxes ) do
| |
| local rfxObject = rfx.new( rfxPage )
| |
| if rfxObject then
| |
| if rfxObject.type == 'rfa' then
| |
| table.insert( rfas, rfxObject )
| |
| elseif rfxObject.type == 'rfb' then
| |
| table.insert( rfbs, rfxObject )
| |
| end
| |
| end
| |
| end
| |
|
| |
| return rfas, rfbs
| |
| end
| |
|
| |
| local function makeReportRows()
| |
| local rfas, rfbs = getRfasRfbsSeparate()
| |
|
| |
| local ret = {}
| |
| if #rfas > 0 then
| |
| table.insert( ret, makeHeading( 'rfa' ) )
| |
| for i, rfaObject in ipairs( rfas ) do
| |
| table.insert( ret, makeRow( rfaObject ) )
| |
| end
| |
| end
| |
| if #rfbs > 0 then
| |
| table.insert( ret, makeHeading( 'rfb' ) )
| |
| for i, rfbObject in ipairs( rfbs ) do
| |
| table.insert( ret, makeRow( rfbObject ) )
| |
| end
| |
| end
| |
| return table.concat( ret )
| |
| end
| |
|
| |
| local function makeReport( args )
| |
| local purgeLink = mw.title.getCurrentTitle():fullUrl( 'action=purge' )
| |
| local header = mw.ustring.format(
| |
| '\n|+ Requests for [[Wikipedia:Requests for adminship|adminship]] and [[Wikipedia:Requests for bureaucratship|bureaucratship]] <span class="rfx-report-purge plainlinks">[%s update]</span>',
| |
| purgeLink
| |
| )
| |
| local rows = makeReportRows() or ''
| |
| if rows == '' then
| |
| rows = '\n|-\n| colspan="10" | No current discussions. <span class="rfx-report-recent">[[WP:Requests for adminship by year|Recent RfAs]], recent RfBs: ([[Wikipedia:Successful bureaucratship candidacies|successful]], [[Wikipedia:Unsuccessful bureaucratship candidacies|unsuccessful]])</span>'
| |
| end
| |
|
| |
| local float = args.float or args.align
| |
| if not float or mw.text.trim(float) == '' then
| |
| float = nil
| |
| end
| |
| local clear = args.clear
| |
| if not clear or mw.text.trim(clear) == '' then
| |
| clear = nil
| |
| end
| |
|
| |
| local style = ''
| |
| if float or clear then
| |
| style = string.format(
| |
| 'style="%s%s"',
| |
| clear and ('clear: ' .. clear .. ';') or '',
| |
| float and ('float: ' .. float .. ';') or ''
| |
| )
| |
| end
| |
|
| |
| return mw.getCurrentFrame():extensionTag{
| |
| name = 'templatestyles', args = { src = 'Module:RFX report/styles.css' }
| |
| } .. mw.ustring.format(
| |
| '\n{| class="wikitable rfx-report" %s%s%s\n|-\n|}',
| |
| style,
| |
| header,
| |
| rows
| |
| )
| |
| end
| |
|
| |
| function p.countRfas()
| |
| local rfas, rfbs = getRfasRfbsSeparate()
| |
| return getTableLength(rfas)
| |
| end
| |
|
| |
| function p.main( frame )
| |
| -- Process the arguments.
| |
| local args
| |
| if frame == mw.getCurrentFrame() then
| |
| args = frame:getParent().args
| |
| for k, v in pairs( frame.args ) do
| |
| args = frame.args
| |
| break
| |
| end
| |
| else
| |
| args = frame
| |
| end
| |
| return makeReport( args )
| |
| end
| |
|
| |
| return p
| |
|
| |
|
| |
|
| ==DONE== | | ==DONE== |
V1.5 limit to just 8 motors for simplification purposes.
For a belt mod, reserve some V1.0 boards and instruct people to add diodes - deals with inventory problem.
New parts for LiPo battery upgrade mod:
battery: sparkfun PRT-00341
charging IC: newark 59J2761
USB Mini B jack: digikey 670-1190-1-ND
JST jack: digikey 455-1719-ND
- Mounting acrylic - how many screws?
- Make a mock-up
- Border pieces - later cut tongue and grooves for snappage
- Ask Rachel for feasability
- Hold the boards in with notches (+$20 for more than 6pts board shape) = no holes!
- No atmel socket - it's tall enough and people can figure that out
- Investigated brownout detection, not useful
- Bigger cap to make the voltage drop less meaning the atmega won't reset when motors ramp up on low batteries
- Switch to internal oscilator for simplicity and power saving, timing vars need retweaking???
- Find/make through-hole usb mini eagle part
- Add copyright info to code and old eagle files
- Batt charging cap not spec'd yet, just copied the 0.1uF part
- Put in RGB LED red=charging green=on