I'm using Google's Vision API to identify certain features in an image. I have the Logo Detection working as the logo comes up in my terminal, but I can't get it to appear on my app screen. It continually prints "No logos found" - here's my code :
//Get logo annotations
let logoAnnotations: JSON = logoResponses["logoAnnotations"]
let numLogos: Int = logoAnnotations.count
var logos: Array<String> = []
if numLogos > 0 {
var allResultsText:String = "Logos: "
for index in 0..<numLogos {
let logo = logoAnnotations[index]["logo"].stringValue
logos.append(logo)
}
for logo in logos {
if logos[logos.count - 1] != logo {
allResultsText += "\(logo), "
} else {
allResultsText += "\(logo)."
}
}
self.allResults.text = allResultsText
} else {
self.allResults.text = "No logos found"
}
}
This is the JSON response I'm getting:
[
{
"boundingPoly": {
"vertices": [
{
"x": 210,
"y": 139
},
{
"x": 229,
"y": 139
},
{
"x": 229,
"y": 179
},
{
"x": 210,
"y": 179
}
]
},
"mid": "/m/04lg33",
"score": 0.18314756,
"description": "Ralph Lauren Corporation"
}
]
How am I to access the value returned for the logo description, this case Ralph Lauren Corporation?
I corrected the issue in my code. Here is the functioning code for anyone that needs it:
let logoAnnotations: JSON = responses["logoAnnotations"]
let numLogos: Int = logoAnnotations.count
var logos: Array<String> = []
if numLogos > 0 {
var logoResultsText:String = " ,"
for index in 0..<numLogos {
let logo = logoAnnotations[index]["description"].stringValue
logos.append(logo)
}
for logo in logos {
if logos[logos.count - 1] != logo {
logoResultsText += ", \(logo), "
} else {
logoResultsText += "\(logo)."
}
}
self.logoResults.text = logoResultsText
} else {
self.logoResults.text = ""
}
I was calling the incorrect index from the logoAnnotations array.
Related
I have included my code below. While it is sort of working, ill get to that in a minute, I feel like there is a better, more efficient, more correct, way to achieve my goal. I have a map for different weather options, in this case, Tornado, Severe Weather and Flash flood warnings. These are all included in one geojson file. The geo json file has a property called LayerId. This determines the time in the loop that the layer would show. I have a simple global map loop that constantly runs from 0 - 11. So if I am on loop 5, then only the data that corresponds with LayerId 5 would be visible. All others would be hidden/removed (which ever is preferred). When the loop hits 6, the layer corresponding to LayerId 5 would go away and LayerId 6 would now show and so on. Once the loop reaches 11, it starts over at 0.
I am not using a leaflet control due to the site requirements so i am using my own simple check box controls. when the check box is clicked, it calls a toggleLayer function to apply filters to my data. If FlashFlood is checked then only the data corresponding to the flash flood would show over the course of the loop IF it has data for flash flood at that interval.
When i said that it is sort of working...in my loop function i have a call to remove a layer. this works except every now and then it throws a null or undefined error. problem is is that its never the same layer. each time i start the application, its a different layer that errors out.
Below i have included a sample of my geojson and the code. The entry point for the code is at the toggleLayer function.
Thanks for any and all help.
GEOJSON FILE
{
"name": "WarningsJson",
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"coordinates": [
[
[ -86.00, 31.00 ],
[ -86.00, 32.00 ],
[ -87.00, 30.00 ],
[ -86.00, 31.00 ]
]
],
"type": "Polygon"
},
"properties": {
"type": null,
"strokeColor": "#ff9aa3",
"StartDateTime": "09/29/2020 7:30:00 AM",
"EndDateTime": "09/29/2020 9:30:00 AM",
"strokeThickness": 20,
"InfoboxTitle": "SFFW",
"Station": "KMOB",
"Identifier": "FFW",
"LayerId": "0"
}
},
{
"type": "Feature",
"geometry": {
"coordinates": [
[
[ -87.00, 32.00 ],
[ -87.00, 33.00 ],
[ -88.00, 31.00 ],
[ -87.00, 32.00 ]
]
],
"type": "Polygon"
},
"properties": {
"type": null,
"strokeColor": "#c0ffd4",
"StartDateTime": "09/29/2020 7:30:00 AM",
"EndDateTime": "09/29/2020 9:30:00 AM",
"strokeThickness": 2,
"InfoboxTitle": "TOR",
"Station": "KMOB",
"Identifier": "TOR",
"LayerId": "1"
}
},......
APPLICATION CODE
var WarnStormModel = (function () {
var layer0 = new L.LayerGroup();
var layer1 = new L.LayerGroup();
var layer2 = new L.LayerGroup();
var layer3 = new L.LayerGroup();
var layer4 = new L.LayerGroup();
var layer5 = new L.LayerGroup();
var layer6 = new L.LayerGroup();
var layer7 = new L.LayerGroup();
var layer8 = new L.LayerGroup();
var layer9 = new L.LayerGroup();
var layer10 = new L.LayerGroup();
var layer11 = new L.LayerGroup();
var warnConditionsLayersGroup = [layer0, layer1, layer2, layer3, layer4, layer5, layer6, layer7, layer8, layer9, layer10, layer11];
var tornadoActive = false;
var svrActive = false;
var ffwActive = false;
const WarnFilter = {
tornado: null,
svr: null,
flood: null
}
function init() {
$.getJSON('/Data/GeoJsonFiles/WarningJsons/Warnings_0.json', function (data) {
L.geoJSON(data, {
style: function (feature) {
return {
color: feature.properties.strokeColor,
fillOpacity: 0
};
},
pane: "warnPane",
onEachFeature: function (feature, layer) {
var popupText = '<div>'
+ '<span style="float: right; cursor: pointer; cursor: hand"</i></span><br>'
+ '<b>LAYER: </b>' + layer.feature.properties.LayerId + '<br>'
+ '<b>TYPE: </b>' + layer.feature.properties.InfoboxTitle + '<br>'
+ '<b>STATION:</b>' + layer.feature.properties.Station + '<br>'
+ '<b>START: </b>' + layer.feature.properties.StartDateTime + '<br>'
+ '<b>END: </b>' + layer.feature.properties.EndDateTime + '<br>';
layer.bindPopup(popupText);
layer._leaflet_id = feature.properties.LayerId;
if (feature.properties.LayerId == "0") { layer0.addLayer(layer); }
else if (feature.properties.LayerId == "1") { layer1.addLayer(layer); }
else if (feature.properties.LayerId == "2") { layer2.addLayer(layer); }
else if (feature.properties.LayerId == "3") { layer3.addLayer(layer); }
else if (feature.properties.LayerId == "4") { layer4.addLayer(layer); }
else if (feature.properties.LayerId == "5") { layer5.addLayer(layer); }
else if (feature.properties.LayerId == "6") { layer6.addLayer(layer); }
else if (feature.properties.LayerId == "7") { layer7.addLayer(layer); }
else if (feature.properties.LayerId == "8") { layer8.addLayer(layer); }
else if (feature.properties.LayerId == "9") { layer9.addLayer(layer); }
else if (feature.properties.LayerId == "10") { layer10.addLayer(layer); }
else if (feature.properties.LayerId == "11") { layer11.addLayer(layer); }
},
filter: function (feature, layer) {
return (
feature.properties.Identifier === WarnFilter.tornado ||
feature.properties.Identifier === WarnFilter.svr ||
feature.properties.Identifier === WarnFilter.flood
)
},
interactive: true
});
}).fail(function (err) { console.log('createWarningsErr: ', err); })
};
//**********//
function isActive(layer) {
if (layer == "TOR") { return tornadoActive; }
else if (layer == "SVR") { return tstrmActive; }
else if (layer == "FFW") { return ffwActive; }
}
var isAnyActive = function () { return tornadoActive || svrActive || ffwActive; }
var toggleLayer = function (layer, checkState) {
switch (layer) {
case "TOR": (checkState) ? WarnFilter.tornado = 'TOR' : WarnFilter.tornado = null; tornadoActive = !tornadoActive;
break;
case "SVR": (checkState) ? WarnFilter.svr = 'SVR' : WarnFilter.svr = null; svrActive = !svrActive;
break;
case "FFW": (checkState) ? WarnFilter.flood = 'FFW' : WarnFilter.flood = null; ffwActive = !ffwActive;
break;
default:
if (checkState) {
for (key in WarnFilter) {
if (WarnFilter.hasOwnProperty(key)) {
debugger
WarnFilter[key] = (key.toString()).toUpperCase();
}
}
}
//set all values in filter themselves to show
else {
for (key in WarnFilter) {
if (WarnFilter.hasOwnProperty(key)) {
WarnFilter[key] = null;
}
}
}
break;
}
showHide(layer, checkState);
}
//**********//
var showHide = function (layer, checkState) {
rerender();
if (isAnyActive() && checkState) {
warnConditionsLayersGroup[GlobalMapLoop.getLoopIndex()].addTo(getMap());
}
else {
warnConditionsLayersGroup[GlobalMapLoop.getLoopIndex()].removeLayer(getMap());
}
}
var loop = function (currentIndex, pastIndex) {
console.log("got to warn loop", currentIndex, pastIndex, isAnyActive())
if (isAnyActive()) {
getMap().removeLayer(warnConditionsLayersGroup[pastIndex]);
getMap().addLayer(warnConditionsLayersGroup[currentIndex]);
}
}
var rerender = (function () {
init();
})
return {
init: init,
toggleLayer: toggleLayer,
loop: loop,
rerender: rerender
};
})();
How can I insert multiple rows in dynamodb using body mapping template of API gateway?
Input to my code is "xyz 1,abc 2" which has information about 2 rows to be inserted.
Only second record which is "abc 2" is getting stored, I want both records to be inserted in the table. Below is the code I have written
#set($rawAPIData = $input.path('$'))
#set ($bulk = $rawAPIData.split(","))
{
"TableName": "tablename",
#foreach( $records in $bulk)
#set ($s = $records.split(" "))
"Item": {
"col1": {
"S": "$s.get(0)"
},
"col2": {
"S": "$s.get(1)"
}
}
#if( $foreach.hasNext ), #end
#end
}
I'm new to this, suggestion would really help
This AWS guide shows how to use API Gateway as a proxy for DynamoDB. It's similar the approach you are trying to take. As a suggestion, it might be better have your api focus on a single row at a time, rather than splitting multiple inputs on ,. For example it would simplify your template somewhat to send requests similar to those found in the guide.
Example Request Body:
{
"col1": "xyz",
"col2": "1"
}
Template (derived from your template code):
{
"TableName": "tablename",
"Item": {
"col1": {
"S": "$input.path('$.col1')"
},
"col2": {
"S": "$input.path('$.col2')"
}
}
}
However, if you want to stick to operating on multiple items, The BatchWriteItem documentation would be worth a read. Following the example, I think this should be your body template:
#set($rawAPIData = $input.path('$'))
#set ($bulk = $rawAPIData.split(","))
{
"RequestItems": {
"tablename": [
#foreach($records in $bulk)
#set ($s = $records.split(" "))
{
"PutRequest": {
"Item": {
"col1": {
"S": "$s.get(0)"
},
"col2": {
"S": "$s.get(1)"
}
}
}
}
#if( $foreach.hasNext ),
#end
]
}
#end
}
I used the similar approach as #Gerand, but I solved it using lambda. Here is the working code:
'use strict';
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
exports.handler = (event, context, callback) => {
var data=event.data;
var bulk = data.split(",");
var toSave = [];
for(var i = 0; i < bulk.length; i++) {
var s=bulk[i].split(" ");
var item = {
"col1": {
S: s[0]
},
"col2": {
S: s[1]
}
};
toSave.push(item);
}
var items = [];
for(var i = 0; i < toSave.length; i++) {
items[i] = {
PutRequest: { Item: toSave[i] }
}
}
var params = {
RequestItems: {
'table_name': items
}
};
dynamodb.batchWriteItem(params, function(err, data) {
console.log("Response from DynamoDB");
if(err) console.log(err);
else console.log(data);
});
};
If a key is duplicated in an array, I want to combine the values of that key. For example, I have the following array.
var arrays = [
["Product":"Item0", "Price":"15"],
["Product":"Item1", "Price":"53"],
["Product":"Item2", "Price":"12"],
["Product":"Item1", "Price":"83"],
["Product":"Item0", "Price":"10"],
["Product":"Item3", "Price":"88"],
["Product":"Item0", "Price":"44"]
]
And I want to change this array like this.
[
["Product": "item0", "Price": "69"],
["Product": "item1", "Price": "136"],
["Product": "item2", "Price": "12"],
["Product": "item3", "Price": "88"]
]
What should I do?
This is the code I wrote. However, if more than two keys are duplicated, the exact value is not displayed. Could you fix a little here or give me a new way at all?
var arrays= [
["Product":"Item0", "Price":"15"],
["Product":"Item1", "Price":"53"],
["Product":"Item2", "Price":"12"],
["Product":"Item1", "Price":"83"],
["Product":"Item0", "Price":"10"],
["Product":"Item3", "Price":"88"],
["Product":"Item0", "Price":"44"]
]
var filteredArrays = [[String:String]]()
var sum : Int = 0
for i in 0..<arrayOfDicts.count {
let Product1 = arrayOfDicts[i]["Product"]
if(i == 0){
filteredArrays.append(arrayOfDicts[i])
} else {
var flag = false
for j in 0..<filteredArrays.count {
let Product2:String = filteredArrays[j]["Product"]!
if Product1 == Product2 {
sum += (Int(arrayOfDicts[i]["Price"]!)! + Int(arrayOfDicts[j]["Price"]!)!)
filteredArrays[j] = ["Product":"\(arrayOfDicts[i]["Product"]!)", "Price":"\(sum)"]
sum = 0
flag = true
}
}
if !flag {
filteredArrays.append(arrayOfDicts[i])
}
}
}
Thank you
Iterate through your products
Check if "Product" contains valid string
Extract price as Int (or float if needed). Default as zero to avoid wrong sum.
Create a dictionary with product name as key and sum the values with same key
Convert dictionary to array
var result = [String : Int]()
for product in arrays {
if let productKey = product["Product"] {
let value = Int(product["Price"] ?? "0")
if result[productKey] == nil, let value = value {
result[productKey] = value
} else if let value = value {
result[productKey]! += value
}
}
}
let newArray = result.map {["Product":$0, "Price": $1]}
Just for fun, not for the faint-hearted, using Swift 4 new method reduce(into:) and Dictionary Key-based subscript with default value:
let result = arrays.reduce(into: [String : Int]()) {
$0[$1["Product"] ?? "", default: 0] += Int($1["Price"] ?? "") ?? 0 }
.map { ["Product": $0, "Price": $1] }
print(result)
"[["Product": "Item0", "Price": 69], ["Product": "Item2", "Price":
12], ["Product": "Item1", "Price": 136], ["Product": "Item3", "Price":
88]]\n"
Who has idea of why this is occurring?
It is giving me error at the Array(places).sorted { $0.1 < $1.1 }.map { $0.0 } part.
let placesByBeacons = [
"12103:16951": [
"Heavenly Sandwiches": 5, // read as: it's 5 meters from
// "Heavenly Sandwiches" to the beacon with
// major 6574 and minor 54631
"Green & Green Salads": 10,
"Mini Panini": 15
],
"648:12": [
"Heavenly Sandwiches": 250,
"Green & Green Salads": 100,
"Mini Panini": 20
],
"17581:4351": [
"Heavenly Sandwiches": 350,
"Green & Green Salads": 500,
"Mini Panini": 170
]
]
func placesNearBeacon(beacon: CLBeacon) -> [String]? {
let beaconKey = "\(beacon.major):\(beacon.minor)"
if let places = self.placesByBeacons[beaconKey] {
let sortedPlaces = Array(places).sorted { $0.1 < $1.1 }.map { $0.0 }
return sortedPlaces
}
return nil
}
You should use sort not sorted. You can also make your function shorter:
func placesNearBeacon(beacon: CLBeacon) -> [String]? {
guard let places = placesByBeacons["\(beacon.major):\(beacon.minor)"] else { return nil }
return places.sort(<).map { $0.0 }
}
I have two tables Category and Sub Category.
Category has toMany Relationship with SubCategory.
SubCategory has toMany Relationship with SubCategory. (SubCategory may have subcategories)
DB Model:
Json Response
{
"response": {
"status": true,
"message": "Category listed",
"code": 200
},
"data": [
{
"description": "Memory Questions",
"id": "QT05",
"title": "Memory",
"subcategory": [
{
"title": "Patterns",
"id": "QT05P",
"subcategory": [
{
"title": "Squares",
"id": "QT05PS",
"demo": {
"type": "image",
"value": "Memory/images/demo_QT05PS.png"
}
},
{
"title": "Circles",
"id": "QT05PC",
"demo": {
"type": "image",
"value": "Memory/images/demo_QT05PC.png"
}
},
{
"title": "Triangles",
"id": "QT05PT",
"demo": {
"type": "image",
"value": "Memory/images/demo_QT05PT.png"
}
},
{
"title": "Rectangles",
"id": "QT05PR",
"demo": {
"type": "image",
"value": "Memory/images/demo_QT05PR.png"
}
}
],
"demo": {
"type": "image",
"value": "Memory/images/demo_QT05P.png"
}
}
]
}
]
}
Sub Category Model Class (CoreData)
extension SubCategory{
func addSubCategory(subcategory:SubCategory) {
var sub = self.mutableSetValueForKey("subcategories")
sub.addObject(subcategory)
}
func setSubCategories(subCategories:NSArray){
var sub = self.mutableSetValueForKey("subcategories")
for subcategory in subCategories {
sub.addObject(subcategory)
}
}
}
Mapping JSON
func mapCategory(dict:NSDictionary?) -> LUBaseResponse? {
if (dict == nil) {
return nil
}
var response = self.mapStatus(dict!)
if (response != nil){
if (response!.status == 1){
let data:NSArray = dict!["data"] as NSArray
var categoryArray = NSMutableArray()
for categoryDict in data {
if (self.fetchCategory(categoryDict["id"] as? String) == nil){
var category = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: self.managedObjectContext!) as? Category
category?.categoryDescription = categoryDict["description"] as String
category?.categoryId = categoryDict["id"] as String
category?.categoryTitle = categoryDict["title"] as String
var subcategory = self.mapSubcategory(categoryDict["subcategory"] as? NSArray,category: category!)
if (subcategory != nil && subcategory?.count > 0){
category?.setSubCategories(subcategory!)
}
categoryArray.addObject(category!)
}
LUCoreData.sharedInstance.saveContext()
}
response?.data = categoryArray
}
}
return response
}
//Issue in this method
private func mapSubcategory(array:NSArray?,category:Category) -> NSMutableArray? {
var subcategoriesObjects = NSMutableArray()
if (array?.count > 0){
var subcategories = array!
NSEntityDescription.insertNewObjectForEntityForName("SubCategory", inManagedObjectContext: self.managedObjectContext!) as? SubCategory
for subcategoryDict in subcategories {
var title = subcategoryDict["title"]
if (self.fetchSubCategory(subcategoryDict["id"] as? String) == nil) {
var subcategory = NSEntityDescription.insertNewObjectForEntityForName("SubCategory", inManagedObjectContext: self.managedObjectContext!) as? SubCategory
subcategory?.title = subcategoryDict["title"] as String
subcategory?.id = subcategoryDict["id"] as String
subcategory?.categoryOf = category
var arraySubCategory = subcategoryDict.objectForKey("subcategory") as? NSArray
if (arraySubCategory?.count > 0){
var nestedSubCategory = self.mapSubcategory(arraySubCategory,category: category)
if (nestedSubCategory != nil){
var sub = nestedSubCategory!.objectAtIndex(0) as SubCategory
println("Sub is \(sub.subcategories)") //Returns Empty
subcategory!.setSubCategories(nestedSubCategory!)
//Issue Here
println("Sub is \(sub.subcategories)")
}
}
subcategoriesObjects.addObject(subcategory!)
}
LUCoreData.sharedInstance.saveContext()
}
}
return subcategoriesObjects
}
Problem:
In JSON Response, you can see that Memory(Category) has subcategories "Patterns", which has nested SubCategories "Square","Circles" etc.
This looping is executed in "mapSubcategory" function
After this line "subcategory!.setSubCategories(nestedSubCategory!)"
In the above images, you can see that when nested subcategory("Squares" which has no further subcategories) added to parent subcategory, the parent subcategory(patterns) is added to Square as subcategory. This cause recursive (Parent -> Child -> Parent -> Child ....). I am not sure how it is recursively adding parent to child.
I have fixed this by removing inverse relationship from subcategory table.