Appending Int to an Array Matlab

I am using an API to get real data times of trains and am trying to get the closest train time to a user entered time and then display that train time, and the next 4 granted the trains are running. I am reading in the information and the code goes through what its supposed to do but when I look at the array its a bunch of [] brackets in 7 cells instead of the calculated numbers. Any suggestions? Code is below with the API
if true
%this is the API link for the live data from Septa this will get 30
%results and see which time is closer to the user entered time
requestInfoSeptaLive = ['http://www3.septa.org/hackathon/NextToArrive/' requestStationSelected '/' requestEndStation '/30'];
%Again tries to get the information and if there is a failure it will give
%a probable cause and terminate the program
try
getInfoSeptaLive = urlread(requestInfoSeptaLive);
catch
if getInfoSeptaLive ~= '[]'
disp...
('Either the arrival/depart stations dont quite match up or theres a server error. Try again.');
return;
else
disp('Unable to fetch the information from Septa, please try again')
return;
end
end
%parses the information returned from the Live API
dataReturnedFromLiveAPI = parse_json(getInfoSeptaLive);
dataReturnedFromLiveAPI = dataReturnedFromLiveAPI{1};
%gets the size of the API in case there are no trains running
sizeOfDataNoTrains = size(dataReturnedFromLiveAPI, 1);
sizeOfData = size(dataReturnedFromLiveAPI, 2);
counter = 0;
for i = 1:sizeOfData
scanForClosestTime = dataReturnedFromLiveAPI{1,i}.orig_departure_time;
trainTimeGivenH = sscanf(scanForClosestTime, '%i');
findColonTrain = strfind(scanForClosestTime, ':');
trainTimeGivenMStr = scanForClosestTime(findColonTrain+1:4);
trainTimeGivenM = int32(str2num(trainTimeGivenMStr));
trainDepartTimeM = (trainTimeGivenH(1,1) * 60) + (trainTimeGivenM);
differenceBetweenTimes = trainDepartTimeM - userEnteredMins;
if trainDepartTimeM < userEnteredMins
differenceBetweenTimes = userEnteredMins - trainDepartTimeM;
end
stopAtEndOfData = sizeOfData;
goodTimeFrame = 60;
closestTime = cell(1, stopAtEndOfData);
storeTheDifference = cell(1, stopAtEndOfData);
if(differenceBetweenTimes < 60)
if (counter < 5)
closestTime{i} = scanForClosestTime;
storeTheDifference{i} = differenceBetweenTimes;
counter = counter + 1;
end
end
end
end

 Accepted Answer

Cedric
Cedric on 9 Mar 2013
Edited: Cedric on 9 Mar 2013
Your stations are probably incorrect.. the following works:
>>requestInfoSeptaLive = 'http://www3.septa.org/hackathon/NextToArrive/Airport%20Terminal%20B/Ardmore/10' ;
>> getInfoSeptaLive = urlread(requestInfoSeptaLive)
getInfoSeptaLive = [{"orig_train":"9472","orig_line":"Airport","orig_departure_time":"11:12PM","orig_arrival_time":"11:30PM","orig_delay":"On time","term_train":"591","term_line":"Paoli\/Thorndale","term_depart_time":"12:19AM","term_arrival_time":"12:35AM","Connection":"30th Street Station","term_delay":"5 mins","isdirect":"false"},{"orig_train":"9472","orig_line":"Airport","orig_departure_time":"11:12PM","orig_arrival_time":"11:30PM","orig_delay":"On time","term_train":"1595","term_line":"Paoli\/Thorndale","term_depart_time":" 1:19AM","term_arrival_time":" 1:35AM","Connection":"30th Street Station","term_delay":"On time","isdirect":"false"},{"orig_train":"474","orig_line":"Airport","orig_departure_time":"11:42PM","orig_arrival_time":"12:00AM","orig_delay":"On time","term_train":"591","term_line":"Paoli\/Thorndale","term_depart_time":"12:19AM","term_arrival_time":"12:35AM","Connection":"30th Street Station","term_delay":"5 mins","isdirect":"false"},{"orig_train":"474","orig_line":"Airport","orig_departure_time":"11:42PM","orig_arrival_time":"12:00AM","orig_delay":"On time","term_train":"1595","term_line":"Paoli\/Thorndale","term_depart_time":" 1:19AM","term_arrival_time":" 1:35AM","Connection":"30th Street Station","term_delay":"On time","isdirect":"false"},{"orig_train":"476","orig_line":"Airport","orig_departure_time":"12:12AM","orig_arrival_time":"12:30AM","orig_delay":"On time","term_train":"1595","term_line":"Paoli\/Thorndale","term_depart_time":" 1:19AM","term_arrival_time":" 1:35AM","Connection":"30th Street Station","term_delay":"On time","isdirect":"false"}]
Do you urlencode station names? I.e. spaces should be converted into % 2 0, & should be converted into & a m p ;, etc ..

9 Comments

yeah it works otherwise but its this one part that the user enters a time and it cycles through all the trains to find the one closest to the time that the user entered then it displays the next 4 trains after the closest one has been chosen....everything else works
Where did you get PARSE_JSON ? Could you paste its output here?
You might be interested in DATENUM for you time conversion/comparison. Look at the following:
>> datenum('11:42PM', 'HH:MMPM')
ans =
7.3524e+05
>> datenum('11:42AM', 'HH:MMPM') < datenum('11:42PM', 'HH:MMPM')
ans =
1
You can use this to find a first start time above user time for example:
>> fmt = 'HH:MMPM' ;
>> startTimes = {'3:10PM', '5:30PM', '8:17PM', '11:42PM'} ;
>> userTime = '10:25PM' ;
>> datenum(startTimes, fmt) < datenum(userTime, fmt)
ans =
1
1
1
0
>> idTime = sum (datenum(startTimes, fmt) < datenum(userTime, fmt)) + 1
idTime =
4
>> startTimes{idTime}
ans =
11:42PM
i used this json parser http://www.mathworks.co.uk/matlabcentral/fileexchange/20565 which works well and i wish i could use that but i already wrote 90% of the code using the way I have it, but that definitely does look like a better way to do what i am doing
Ok, there is no more train I guess and I receive nothing anymore. I tested some lines of code using the output that I pasted above, and I would bring the following small modification to your code: replace the whole loop plus the code that is likely to come after for analyzing closestTime and |storeTheDifference |
for i = 1:sizeOfData
...
end
...
with something like:
buffer_SA = [dataReturnedFromLiveAPI{:}] ;
startTimes = {buffer_SA(:).orig_departure_time} ;
fmt = 'HH:MMPM' ;
idTime = sum(datenum(startTimes, fmt) < datenum(userTime, fmt)) + 1 ;
foundTime = startTimes{idTime} ;
adapted to your case (in particular for the format of userTime). If you really wanted to math a minimal time difference, you could replace the line that defines idTime with
timeDifs = abs(datenum(startTimes, fmt) - datenum(userTime, fmt)) ;
idTime = find(timeDifs == min(timeDifs), 1) ;
However, if you want to keep your solution, I guess that you want to move the lines
closestTime = cell(1, stopAtEndOfData) ;
storeTheDifference = cell(1, stopAtEndOfData);
before the start of the for loop, because you put them at a place where they re-initialize both cell arrays at each iteration of the loop. You could also use counter (starting at 1) to index both cell arrays if you don't want to manage empty cells afterwards.
Finally, note that both solutions will fail when start times cross the midnight boundary as none is using a full date (that is not available in the struct returned by SEPTA).
I made these modifications. I set the time to 4:00 (cause it was the closest whole time at the time i tested it). It returned 2 times...which was better than what I had. Then I entered 4:45 and it only returned one time when there are 6 more trains to arrive at that station. The cell array also adapted to the number of trains which is also good, instead of always staying a 1x7 cell array. But I still dont know why it is only returning 1 time when it knows there are 6 trains coming. Im just pasting the block i changed
if true counter = 0; stopAtEndOfData = sizeOfData; goodTimeFrame = 60; closestTime = cell(1, stopAtEndOfData); storeTheDifference = cell(1, stopAtEndOfData);
for i = 1:sizeOfData
scanForClosestTime = dataReturnedFromLiveAPI{1,i}.orig_departure_time;
trainTimeGivenH = sscanf(scanForClosestTime, '%i');
findColonTrain = strfind(scanForClosestTime, ':');
trainTimeGivenMStr = scanForClosestTime(findColonTrain+1:4);
trainTimeGivenM = int32(str2num(trainTimeGivenMStr));
trainDepartTimeM = (trainTimeGivenH(1,1) * 60) + (trainTimeGivenM);
differenceBetweenTimes = trainDepartTimeM - userEnteredMins;
if trainDepartTimeM < userEnteredMins
differenceBetweenTimes = userEnteredMins - trainDepartTimeM;
end
if(differenceBetweenTimes < 60)
if (counter < 5)
counter = counter + 1;
closestTime{counter} = scanForClosestTime;
storeTheDifference{counter} = differenceBetweenTimes;
end
end
end
end
end
Cedric
Cedric on 10 Mar 2013
Edited: Cedric on 10 Mar 2013
Let's simplify a bit what you've done. The whole block
trainTimeGivenH = sscanf(scanForClosestTime, '%i');
findColonTrain = strfind(scanForClosestTime, ':');
trainTimeGivenMStr = scanForClosestTime(findColonTrain+1:4);
trainTimeGivenM = int32(str2num(trainTimeGivenMStr));
trainDepartTimeM = (trainTimeGivenH(1,1) * 60) + (trainTimeGivenM);
can be replaced by
timeNum = sscanf(scanForClosestTime, '%d:%d') ;
trainDepartTimeM = timeNum(1)*60 + timeNum(2) ;
Then the block
differenceBetweenTimes = trainDepartTimeM - userEnteredMins;
if trainDepartTimeM < userEnteredMins
differenceBetweenTimes = userEnteredMins - trainDepartTimeM;
end
can be replaced by
differenceBetweenTimes = abs(trainDepartTimeM - userEnteredMins) ;
With that, your approach seems to be working on my system.. settings userEnteredMins to 660 (=11:00PM), I get after the loop:
>> closestTime
closestTime =
'10:12PM' '10:42PM' '11:12PM' '11:42PM' [] [] [] [] [] []
>> storeTheDifference
storeTheDifference =
[48] [18] [12] [42] [] [] [] [] [] []
If you want to understand more clearly what happens with your code, I advice you to use the debugger. For that, put your cursor on the starting line of the for loop and press F12 to set a break point (your also have to comment out any clear all that you might have in your code, because they clear breakpoints). Then run your code and you'll see that it will be executed until the break point and stop (in the debugger; the command window will indicate it by setting the prompt to K>> instead of just >>). At this point you can press F10 to step in the code line by line. Doing so and looking at the state of variables each time your step will allow you to have a full understanding of what is happening and when.
A last comment: I don't understand why you test if counter < 5 at the place where you do it now. Imagine that the user time is 11PM and the first four entries in the time table are 10PM, 10:01PM, 10:02PM, 10:03PM, followed by 10:55PM and 11:05PM. In that case, best matches are clearly entries 5 and 6, but you won't store them because counter will already be above 4. It seems to me that you should store all potential matches, and only after, when you process the whole list of matches, keep the four best ones.
I got it all worked out thanks a lot!
My pleasure!

Sign in to comment.

More Answers (0)

Asked:

on 9 Mar 2013

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!