I've been gathering information using api calls from my jira. Information gathered is saved in a body file and it has the following content:
No tickets:
{"startAt":0,"maxResults":50,"total":0,"issues":[]}{"startAt":0,"maxResults":50,"total":0,"issues":[]}
One Ticket:
{"expand":"names,schema","startAt":0,"maxResults":50,"total":1,"issues":[{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"456881","self":"https://myjira...com","key":"TICKET-1111","fields":{"summary":"[TICKET] New Test jira","created":"2018-12-17T01:47:09.000-0800"}}]}{"expand":"names,schema","startAt":0,"maxResults":50,"total":1,"issues":[{"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields","id":"456881","self":"https://myjira...com","key":"TICKET-1111","fields":{"summary":"[TICKET] New Test jira","created":"2018-12-17T01:47:09.000-0800"}}]}
Two Tickets:
{expand:schema,names,startAt:0,maxResults:50,total:2,issues:[{expand:operations,versionedRepresentations,editmeta,changelog,renderedFields,id:456881,self:https://myjira...com,key:TICKET-1111,fields:{summary:[TICKET] New Test jira,created:2018-12-17T01:47:09.000-0800}},{expand:operations,versionedRepresentations,editmeta,changelog,renderedFields,id:320281,self:https://myjira...com,key:TICKET-2222,fields:{summary:[TICKET] Test jira,created:2016-03-18T07:58:52.000-0700}}]}{expand:schema,names,startAt:0,maxResults:50,total:2,issues:[{expand:operations,versionedRepresentations,editmeta,changelog,renderedFields,id:456881,self:https://myjira...com,key:TICKET-1111,fields:{summary:[TICKET] New Test jira,created:2018-12-17T01:47:09.000-0800}},{expand:operations,versionedRepresentations,editmeta,changelog,renderedFields,id:320281,self:https://myjira...com,key:TICKET-2222,fields:{summary:[TICKET] Test jira,created:2016-03-18T07:58:52.000-0700}}]}
etc..
Using this code I've been able to gather total open tickets:
std::ifstream t("BodyOpenIssues.out");
std::string BodyString((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
// Removing Quotes
BodyString.erase(std::remove(BodyString.begin(), BodyString.end(), '"'), BodyString.end());
int Result = 0;
unsigned first = BodyString.find("total:");
unsigned last = BodyString.find(",issues");
std::string TotalOpenIssues = BodyString.substr(first + 6, last - (first + 6));
Result = std::stoi(TotalOpenIssues);
return Result;
Using a second function I'm trying to get the keys based on total open tickets.
if (GetOpenIssuesNumber() > 0)
{
std::ifstream t("BodyOpenIssues.out");
std::string BodyString((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
// Removing Quotes
BodyString.erase(std::remove(BodyString.begin(), BodyString.end(), '"'), BodyString.end());
unsigned first = BodyString.find("key:TICKET-");
unsigned last = BodyString.find(",fields");
std::string TotalOpenIssues = BodyString.substr(first + 11, last - (first + 11));
String^ Result = gcnew String(TotalOpenIssues.c_str());
return "TICKET-" + Result;
}
else
{
return "No open issues found";
}
What I mean is:
If Total is 1 to search from the beginning and find the first key TICKET-1111.
If Total is 2 to search from the beginning and get the first key TICKET-1111 then to continue from there and to find the next key TICKET-2222.
And based on that total to find that many keys in that string.
I got lost from all the casting between the types as ifstream reads the file and I save the result in std::string. After the find I save the result in System::String to use it in my Label.. I've been researching and found out that I can use char array but I can't make it dynamic based on BodyString.length().
If more information is required please let me know.
Any suggestions are really appreciated! Thank you in advance!
I went for nlohmann json library. It has everything I need. Thank you Walnut!
These are formatted as JSON. You should use a JSON library for C++ and parse the files with that. Using search/replace is unnecessary complicated and you will likely run into corner cases you haven't considered sooner or later (do you really want the code to randomly miss tickets, etc.?). Also String^ is not C++. Are you writing C++/CLI instead of C++? If so, please tag c++-cli instead of c++. – walnut
I'm trying to adapt KG4SGP's RTTY modulator to send a textfile instead of a fixed char array. I'm getting Strings by the readLine() method, altering these Strings by replacing certain values and then copy the altered String to a charArray.
I changed his globalchar msg[] = "\n\nCQ CQ CQ DE KG4SGP KG4SGP KG4SGP KN\n\n"; tochar msg[70]; and hoped to have this running instead;
while(text.available()) {
String lin= readLine();
lin.toLowerCase();
if (lin.indexOf("&")) {
if (lin.indexOf("&de ")) {
lin.replace("&de ", "de ");
result = calculateDayOfYear(dag,maand,jaar);
lin.replace("juldate" , String(result));
lin.replace("hour", String(uur));
lin.replace("min", String(mins));
}
if (lin.indexOf("month")) {
lin.replace("&","");
lin.replace("day", String(dag));
lin.replace("hour", String(uur));
rmin=random(1, mins);
lin.replace("rndmin", String(rmin));
lin.replace("month", (months[maand-1]));
lin.replace("year", kortjaar );
}
lin.toUpperCase();
lin.toCharArray(msg,lin.length()+1);
//Serial.println(msg);
}
Well, whatever I did or tried, I'm never getting any charArray to correctly identify the current character and translate it.. :-( It seems to all come out of the timerfunction
All suggestions welcome
In a test, I am injecting an example URL with a colon for a port number ("http://example.com:port") into my configuration, which is then used by my production code to construct a UriComponentsBuilder which ultimately creates a URI String.
However, that colon character is being converted into a forward slash by the UriComponentsBuilder, as demonstrated in this MCVE:
#Test
public void portNumberFromHttpUrl() {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com:port");
String uriString = builder.toUriString();
assertThat(uriString).isEqualTo("http://example.com:port");
}
This test fails as follows:
org.junit.ComparisonFailure:
Expected :"http://example.com:port"
Actual :"http://example.com/port"
Why is the : being converted to a /?
The MCVE helped me answer this myself almost immediately, but I'll leave the question here because I couldn't find the same question here or anywhere else online, and I guess it might save someone else some time:
It seems that UriComponentsBuilder recognises that a port should be a number, so this (more realistic) case passes:
#Test
public void portNumberFromHttpUrl() {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com:123");
String uriString = builder.toUriString();
assertThat(uriString).isEqualTo("http://example.com:123");
}
From a little more investigation it seems that it puts a / before the first non-numeric character that it encounters after a :, so:
http://example.com:a123 -> http://example.com/a123
http://example.com:12a3 -> http://example.com:12/a3
http://example.com:123a -> http://example.com:123/a
Not immediately obvious, but makes sense, I guess.
When I use the following:
$location.path('/product/ninja-game'); //No error in console but the path isn't changed
The path is not changed but it works when I use following:
$location.path('/product/ninja_game');
Is there anything specific to hyphen/dash character in angularjs path. I couldn't find anything specific in the docs.
Code:
$scope.buildProductDetails = function(product) {
var tempTitle = product.title.toLowerCase();
tempTitle = tempTitle.replace(/adobe/g, "").trim();
tempTitle = tempTitle.replace(/\s+/g, '-'); //replacing space with hyphen
console.log(tempTitle);
$location.path('/product/' + tempTitle);
}
Hyphen/dash should not be a problem
Probably the problem is in the variable tempTitle.
Hardcode the path like $location.path('/product/ninja-game'); and check just to see whether the problem in the variable tempTitle.
problem
I have a Type:
data FSObject = Folder String [FSObject] | File String
and I need to make a function
search :: String -> FSObject -> Maybe String
that returns a path to File that we are searching for (if exists)
(String in search function should be equal to the name (the String in File object (w/o path)) of the searched File.
my thoughts/tryings
I feel like I am not doing it properly- in a functional way. I am new to this language so I am sorry for the following code.
I was trying to do this for several hours. I was trying like this:
heler function contains that returns true if given FSObject contains File that we are looking for
helper function that returns first element with the File (using previous function and "find" function)
helper function to deal with conversion from Maybe String to String
My search function would check if there is the File, if no-> return Nothing, else return Just with String computed somehow using recursion
I can paste my work but I don't know how to make it work, its totally unreadable etc.
Do some1 has hints/comments to share? How to properly deal with Maybe in this kind of problems?
You can do this using recursion.
findPath::String->FSObject->Maybe String
findPath name (File name') | name == name' = Just name
findPath _ (File _) = Nothing
findPath name (Folder path contents) =
fmap ((path ++ "/") ++) $ msum $ map (findPath name) contents
The only tricky point is the last part. Breaking the last line apart....
map (findPath name) contents
will output a list of subresults
[Just "a/b/filename", Nothing, Just "c/d/filename", ....]
msum will take the first Just in the list, throwing the rest away (and, by laziness, nothing further than that first value will actually be created)
Finally, the path is prepended (the fmap is there to reach inside the Maybe)
While #jamshidh solution is short, it isn't modular and the final result. Here is my process of writing the program. Two main points:
I'll use so called "generate then search" approach: first I generate paths for all files, then I search the collection for the right path
I'll store path as list of components - this way the code will be more generic (in Haskell more generic code is less error-prone) and I will insert path separators afterwards in a small function (so I can do one thing at a time which is easier).
Ok I need function allPaths that gives me list of all files along with their paths. All paths of a single file is that single file, and all paths of a folder is concatenated collections of paths from children with prepended folder name:
allPaths (File file) = singleFile file
allPaths (Folder folder children) = concatMap (addFolder folder . allPaths) children
I actually wrote the code top-down. So I didn't bother defining singleFile and addFolder at this point. Single file is simple:
singleFile file = [(file, [])]
addFolder adds f to second component of a tuple. There is a function in Control.Arrow for that already, but I add its implementation here for simplicity:
second f (a,x) = (a, f x)
addFolder f files = map (second (f:)) files
When I was learning Haskell it was hard to write such code at once, but now it's automatic and without intermediate steps.
Now we basically implement search by filtering all matching files, taking the first match and extracting the path. Oh, there is already function lookup in the standard library for that:
search fileToSearch l = lookup fileToSearch $ allPaths l
It took me quite a while to figure out how to compose lookup and allPaths. Fortunately the order in the tuple was chosen correctly by accident.
Note that you still need to convert folder list to a path by inserting separators and appending filename as necessary using concatMap.
You should create a recursive function using an accumulation parameter to save the current path where you're searching. It would be something like this:
search str (File f) = if str == f then Just str else Nothing
search str (Directory dir (x:xs)) =
Just (sear str [] (Directory dir (x:xs))) where
sear str path (File f) = if str == f then (path ++ "/" ++ str ++ "|") else []
sear str path (Directory y []) = []
sear str path (Directory dir (x:xs)) = sear str (path ++ "/" ++ dir) x ++ sear str path (Directory dir xs)
I hope it's helpful for you.