So far I have created a loop that takes a user input and compares it to the current time, and sounds an alarm if there is a match. When I run this it runs at 99% CPU usage and makes my computer nearly unusable. I am looking for a way to run this on a much lower priority or better yet, an alternative to a loop. All the other answers I have seen either don't address the user input through text, or isn't in swift. Any help is much appreciated and below is the function that compares the two times, the alarmHour and alarmMinute variables are the ones that the user enters.
func runTimer() {
var rightTime:Bool
do {
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
let hour = String(components.hour)
let minutes = String(components.minute)
if (hour == globe.alarmHour && minutes == globe.alarmMinutes){
rightTime = true
} else {
rightTime = false
}
} while (rightTime == false)
if (rightTime == true) {
prepareAudio()
AlarmSound.play()
}
}
Ugh. Your do/while loop is in fact a very bad way to do it for the reasons you've outlined.
In most cases an NSTimer is the way to go. Take a look at the 'scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:` method.
You create a timer and schedule it and it calls your selector at the desired time.
NSTimers aren't totally exact. They can be off by around 50ms, but for displaying an alarm to the user that's fine.
Related
I am trying to collect the participants' responses (i.e., the first key they press on the keyboard) and their reaction time (i.e., the time elapsed since the presentation of a picture and the response). I am using the KbQueueXXX functions in Psychtoolbox, but I am not sure if I am using them properly.
Thanks for your help.
Dear Psychtoolbox users,
I wrote a script to run a 2AFC task where participants must respond within a fixed deadline of 2 seconds. If participants respond earlier, then they move to the subsequent trial straight away. To collect their responses (i.e., the first key they pressed and their RT), I coded a custom function that incorporates KbQueueCheck(). I am now reviewing and debugging my script but I have some doubts about the KbQueueXXX functions. I would be grateful if you could give me some feedback.
Task script
In a mixture of code and pseudocode, here is what I am doing.
KbQueueCreate(KEYBOARD, KEYS_OF_INTEREST);
KbQueueStart(KEYBOARD);
% TRIALS' LOOP STARTS
for iTrial = 1:nTrials
KbQueueFlush(KEYBOARD);
% show stimulus and record its onset and offset times
respDeadline = stimulusOffset + 2;
collectResponse(KEYBOARD, respDeadline, stimulusOnset); % <- KbQueueCheck() here!
end
% TRIALS' LOOP ENDS
KbQueueStop(KEYBOARD);
KbQueueRelease(KEYBOARD);
Custom function
Below is my custom function collectResponse() where I embedded KbQueueCheck().
function [choice, rt, choiceTime, firstPress, keyCodes, pressed] = collectResponse(deviceIndex, untilTime, targetOnset)
%% LOOK FOR KEYPRESSES
pressed = false;
while pressed == false && GetSecs <= untilTime
[pressed, firstPress] = KbQueueCheck(deviceIndex);
end
%% PROCESS KEYPRESSES
if pressed == false % NO KEYS WERE PRESSED
keyCodes = NaN;
firstPress = NaN;
choiceTime = NaN;
choice = NaN;
rt = NaN;
else % ONE OR MORE KEYS WERE PRESSED
keyCodes = find(firstPress > 0); % all keypresses
choiceTime = min(firstPress(keyCodes)); % ts of first keypress
choice = find(firstPress == choiceTime); % first keypress
if length(choice) > 1
% handle simultaneous keypresses
choice = -999;
end
rt = choiceTime - targetOnset; % reaction time
end
end
My questions
I am not sure whether I am calling KbQueueXXX functions correctly and whether they are in the expected position.
Shall I keep KbQueueCreate()/KbQueueStart() and KbQueueStop()/KbQueueRelease() respectively before and after the trials’ loop?
Shall I rather just KbQueueStart(), KbQueueCheck(), and KbQueueStop() at each trial iteratively?
Is it OK to KbQueueFlush() at the beginning of each trial, before the presentation of a new stimulus?
Is my custom function collectResponse() fit for the purpose I described at the top of this post?
Thank you very much for your time, I look forward to knowing your thoughts.
Kind regards,
Valerio
OS: Windows 10
MATLAB: 9.10.0.1851785 (R2021a) Update 6
PTB: 3.0.18 - Flavor: beta - Corresponds to SVN Revision 13009
The original post can be found in the Psychtoolbox forum.
KbQueueXXX functions: which to use and where do they go in relation to the trials' loop?
I am currently trying to write a for loop that will loop until it comes to a blank cell at which point I want the loop to end. That part is easy. Today I stumbled upon something that made it even easier, potentially. The reason I am here is because I decided to try the following which worked however, I am not sure if this is "janky code just working" or if this is the real deal as I, a no professional programmer, have never run into this simplified "not logic" syntax before.
for(var i = 1;!parseSheet.getRange(i,2).isBlank();i++)
My interest is in the "!" before the logic argument.
The point of this post is the following
Is what I have done here, "!" before my logic statement, really a thing or is this just some extremely simple and to the point fluke that is working well for me for some reason?
Can I, as a rule, treat "!" before a logic statement like this the same as "not(logic)" or at least treat it a a rule with some exceptions?
What are some KEY, just the save your bacon from the fire stuff, best practices?
What are some common pitfalls?
Perhaps most importantly, what is the terminology for this? What would you call it when you place a "!" before a logic statement?
I am certain that this is something basic to determine on my own except that I have found it very difficult to search for as I do not know the terminology to use. My results are a flood of "!=" results, general Boolean information, or stuff about not statements that do not look as simple as what seems to be working in my for loop. I think this would be helpful to a lot of people as I see a flood or results close to this but not quite as simplified.
I apologize if this is a repost. This is, in my opinion, complicated to try and phrase into a search query and especially so when I am not sure of the terminology regarding what it is that I am looking for.
! is logical NOT operator.
The for loop syntax is:
for ([initialization]; [condition]; [final-expression])
[statement]
All those four parameters initialization, condition, final-expression and statement are optional. You can pick and chose and combine any parameter you like, as noted in the MDN link above. The second parameter is a condition, a logical condition. So, it's syntactically valid to use a logical NOT operator to modify the logical condition as you see fit. It's just preference(a better one too).
While the logic is correct and there are no pitfalls, in this case, the condition itself(without considering the NOT !) will be making expensive calls (as TheWizEd said in the comments). If you make the same loop using arrays, it'll be better:
const values = parseSheet.getRange('B1:B'+parseSheet.getLastRow()).getValues()
for(let i = 0;!(values[i][0] === ''); i++);
This is not an answer but I was curious about the different ways of finding the first blank cell. I created a sheet with 990+ rows and row 991 is blank.
The OP's suggested method.
Sheet.getDataRange().getValues()
Array.findIndex()
Range.getNextDataCell()
Code.gs
function test() {
try {
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
let start = new Date();
for( var i=1; !sheet.getRange(i,1).isBlank(); i++ );
let end = new Date();
console.log("!sheet.getRange: "+(end.valueOf()-start.valueOf())+" msec - i = "+i);
start = new Date();
let values = sheet.getDataRange().getValues();
for( i=0; i<values.length; i++ ) {
if( values[i][0] === "" ) break;
}
end = new Date();
console.log("Sheet.getDataRange: "+(end.valueOf()-start.valueOf())+" msec - i = "+i);
start = new Date()
// get it again to be comparable
values = sheet.getDataRange().getValues();
i = values.findIndex( row => row[0] == "" );
end = new Date()
console.log("Array.findIndex: "+(end.valueOf()-start.valueOf())+" msec - i = "+i);
start = new Date();
let range = sheet.getRange(1,1,sheet.getLastRow(),1);
range = range.getNextDataCell(SpreadsheetApp.Direction.DOWN);
end = new Date();
console.log("Range.getDataRegion: "+(end.valueOf()-start.valueOf())+" msec - i = "+range.getRowIndex());
}
catch(err) {
console.log(err)
}
}
Execution log
3:10:59 PM Notice Execution started
3:11:03 PM Info !sheet.getRange: 3022 msec - i = 991
3:11:03 PM Info Sheet.getDataRange: 153 msec - i = 990
3:11:03 PM Info Array.findIndex: 148 msec - i = 990
3:11:03 PM Info Range.getDataRegion: 189 msec - i = 990
3:11:03 PM Notice Execution completed
Im Vladimir Grygov and I have very serious problem.
In our work we now work on really hard algorithm, which using limits to cout the specific result.
Alghoritm is veary heavy and after two months of work we found really serious problem. Our team of analytics told me to solve this problem.
For the first I tell you the problem, which must be solve by limits:
We have veary much datas in the database. Ec INT_MAX.
For each this data we must sort them by the alghoritm to two groups and one must have red color interpretation and second must be blue.
The algorithm counts with ID field, which is some AUTO_INCREMENT value. For this value we check, if this value is eequal to 1. If yeas, this is red color data. If it is zero, this is blue data. If it is more. Then one, you must substract number 2 and check again.
We choose after big brainstorming method by for loop, but this was really slow for bigger number. So we wanted to remove cycle, and my colegue told me use recursion.
I did so. But... after implementation I had got unknown error for big integers and for example long long int and after him was wrote that: "Stack Overflow Exception"
From this I decided to write here, because IDE told me name of this page, so I think that here may be Answer.
Thank You so much. All of you.
After your comment I think I can solve it:
public bool isRed(long long val) {
if (val==1)
{return true; }
else if (val==0)
{ return false; }
else { return isRed(val - 2); }
}
Any halfway decent value for val will easily break this. There is just no way this could have worked with recursion. No CPU will support a stacktrace close to half long.MaxInt!
However there are some general issues with your code:
Right now this is the most needlesly complex "is the number even" check ever. Most people use Modulo to figure that out. if(val%2 == 0) return false; else return true;
the type long long seems off. Did you repeat the type? Did you mean to use BigInteger?
If the value you substract by is not static and it is not solveable via modulo, then there is no reason not to use a loop here.
public bool isRed (long long val){
for(;val >= 0; val = val -2){
if(value == 0)
return false;
}
return true;
}
I want to create a random string of a fixed length (8 chars in my use case) and the generated string has to be case sensitive and unique against a blacklist. I know this sounds like a UUID but I have a specific requirement that prevents me from utilizing them
some characters are disallowed, i.e. I, l and 1 are lookalikes, and O and 0 as well
My initial implementation is solid and solves the task but performs poorly. And by poorly I mean it is doomed to be slower and slower every day.
This is my current implementation I want to optimize:
private function uuid()
{
$chars = 'ABCDEFGHJKLMNPQRSTVUWXYZabcdefghijkmnopqrstvuwxyz23456789';
$uuid = null;
while (true) {
$uuid = substr(str_shuffle($chars), 0, 8);
if (null === DB::table('codes')->select('id')->whereRaw('BINARY uuid = ?', [$uuid])->first())) {
break;
}
}
return $uuid;
}
Please spare me the critique, we live in an agile world and this implementation is functional and is quick to code.
With a small set of data it works beautifully. However if I have 10 million entries in the blacklist and try to create 1000 more it fails flat as it takes 30+ minutes.
A real use case would be to have 10+ million entries in the DB and to attempt to create 20 thousand new unique codes.
I was thinking of pre-seeding all allowed values but this would be insane:
(24+24+8)^8 = 9.6717312e+13
It would be great if the community can point me in the right direction.
Best,
Nikola
Two options:
Just use a hash of something unique, and truncate so it fits in the bandwidth of your identifier. Hashes sometimes collide, so you will still need to check the database and retry if a code is already in use.
s = "This is a string that uniquely identifies voucher #1. Blah blah."
h = hash(s)
guid = truncate(hash)
Generate five of the digits from an incrementing counter and three randomly. A thief will have a worse than 1 in 140,000 chance of guessing a code, depending on your character set.
u = Db.GetIncrementingCounter()
p = Random.GetCharacters(3)
guid = u + p
I ended up modifying the approach: instead of checking for uuid existence on every loop, e.g. 50K DB checks, I now split the generated codes into multiple chunks of 1000 codes and issue an INSERT IGNORE batch query within a transaction.
If the affected rows are as many as the items (1000 in this case) I know there wasn't a collision and I can commit the transaction. Otherwise I need to rollback the chunk and generate another 1000 codes.
I don't really like people who write with Caps Lock. In addition the aversion, it defaces the whole application. I am wondering how to prevent users writing all characters with caps lock. I cannot force all text to lowercase due to special names and abbreviations. What logic should I use?
Politely decline their posts—explaining why—if the number of capital letter exceeds the number of lowercase letters by more than 30, say.
Don't implement this on a FORTRAN forum
You could check how many upper case characters are in a word, then limit that. Someone above has given the example of names like 'McLaren', this way would allow that. the down side is, if you put the maximum on 3, 'LOL' would stil be possible.
The way to go would be to take the length of the word 'McLaren' would be 7 then cap it on a percentage like 20%, this enables longer words to have more uppercase characters, but not be all caps. (nothing will completely prevent it, but this will make it harder for them.)
Fun fact, today is international caps-lock day. :)
keypress: function(e) {
var ev = e ? e : window.event;
if (!ev) {
return;
}
var targ = ev.target ? ev.target : ev.srcElement;
// get key pressed
var which = -1;
if (ev.which) {
which = ev.which;
} else if (ev.keyCode) {
which = ev.keyCode;
}
// get shift status
var shift_status = false;
if (ev.shiftKey) {
shift_status = ev.shiftKey;
} else if (ev.modifiers) {
shift_status = !!(ev.modifiers & 4);
}
// At this point, you have the ASCII code in "which",
// and shift_status is true if the shift key is pressed
}
Source --http://24ways.org/2007/capturing-caps-lock