Data changes only after closing the app in the background in SwiftUI - core-data

I´m using core data to safe date in my iOS app. On button click I safe data to core data. In a separate tab the data is used in computed properties to get averages out of the added values and display them to the view. This works but the data only updates after the app is closed in the background. I've tried to pass the data into a viewModel and pass the data with an Environment Object but that didn't work (Sorry if this isn't very precise, that's my first post).
import SwiftUI
struct HabitStatistics: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(sortDescriptors: []) var habits: FetchedResults<Habit>
// MARK: Computing EarlyBird Property
var filteredEarlyBird: Int {
var earlyBird = 0
var counter = 0
for h in habits {
let component = Calendar.current.dateComponents([.hour, .minute], from: h.getUpTime ?? Date())
let hour = component.hour ?? 0
let minute = component.minute ?? 0
let difference = (hour * 60 + minute) - 270
earlyBird += difference
counter += 1
}
if counter != 0 {
earlyBird /= counter
return earlyBird
} else {
return 0
}
}
// MARK: Computing ateMeat Property
var filteredMeat: Int {
var total: Int {
if habits.count == 0 {
return 1
} else {
return habits.count
}
}
var count = 0
var perc = 0
for h in habits {
if h.ateMeat == 0 {
count += 1
}
}
perc = count * 100 / total
return perc
}
// MARK: Computing ateSuger Property
var filteredSugar: Int {
var total: Int {
if habits.count == 0 {
return 1
} else {
return habits.count
}
}
var count = 0
var perc = 0
for h in habits {
if h.ateSugar == 0 {
count += 1
}
}
perc = count * 100 / total
return perc
}
// MARK: Computing didSports Property
var filteredSport: Int {
var total: Int {
if habits.count == 0 {
return 1
} else {
return habits.count
}
}
var count = 0
var perc = 0
for h in habits {
if h.didSports == 1 {
count += 1
}
}
perc = count * 100 / total
return perc
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
// Headline
Text("This Week")
.bold()
VStack {
RectangleCard(textLeft: "Meatfree", textRight: "\(filteredMeat) %")
RectangleCard(textLeft: "Sugarfree", textRight: "\(filteredSugar) %")
RectangleCard(textLeft: "Sportsrate", textRight: "\(filteredSport)%")
RectangleCard(textLeft: "Average Time Loss", textRight: "\(filteredEarlyBird) Min lost")
}
}
}
}
import SwiftUI
struct DailyForm: View {
#Environment(\.managedObjectContext) private var viewContext
#EnvironmentObject var model: HabitModel
#State var getUpTime = Date()
#State var ateMeat = InputOptions.nein
#State var ateSugar = InputOptions.nein
#State var didSports = InputOptions.nein
var body: some View {
VStack {
HStack {
Button("Clear") {
clear()
}
Spacer()
Button("Add") {
addHabit()
clear()
}
}
.padding()
ScrollView (showsIndicators: false) {
VStack (alignment: .leading) {
AddPickerValues(getUpTime: $getUpTime,
ateMeat: $ateMeat,
ateSugar: $ateSugar,
didSports: $didSports)
}
.padding(.horizontal)
}
}
}
func clear() {
getUpTime = Date()
ateMeat = InputOptions.nein
ateSugar = InputOptions.nein
didSports = InputOptions.nein
}
func addHabit() {
let habit = Habit(context: viewContext)
habit.id = UUID()
habit.getUpTime = getUpTime
habit.ateMeat = convertValue(habit: ateMeat)
habit.ateSugar = convertValue(habit: ateSugar)
habit.didSports = convertValue(habit: didSports)
do {
try viewContext.save()
}
catch {
// Couldn't save the recipe
}
}
func convertValue (habit: InputOptions) -> Int {
if habit == InputOptions.nein {
return 0
} else {
return 1
}
}
}

This is working:
Main:
#main
struct coretatatestApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
TabView {
DailyForm()
.tabItem {
Label("Daily Form", systemImage: "calendar" )
}
HabitStatistics()
.tabItem {
Label("Statistics", systemImage: "chart.bar.fill" )
}
}
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
Statistics:
struct HabitStatistics: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(sortDescriptors: []) var habits: FetchedResults<Habit>
// MARK: Computing EarlyBird Property
var filteredEarlyBird: Int {
var earlyBird = 0
var counter = 0
for h in habits {
let component = Calendar.current.dateComponents([.hour, .minute], from: h.getUpTime ?? Date())
let hour = component.hour ?? 0
let minute = component.minute ?? 0
let difference = (hour * 60 + minute) - 270
earlyBird += difference
counter += 1
}
if counter != 0 {
earlyBird /= counter
return earlyBird
} else {
return 0
}
}
// MARK: Computing ateMeat Property
var filteredMeat: Int {
var total: Int {
if habits.count == 0 {
return 1
} else {
return habits.count
}
}
var count = 0
var perc = 0
for h in habits {
if h.ateMeat == false {
count += 1
}
}
perc = count * 100 / total
return perc
}
// MARK: Computing ateSuger Property
var filteredSugar: Int {
var total: Int {
if habits.count == 0 {
return 1
} else {
return habits.count
}
}
var count = 0
var perc = 0
for h in habits {
if h.ateSugar == false {
count += 1
}
}
perc = count * 100 / total
return perc
}
// MARK: Computing didSports Property
var filteredSport: Int {
var total: Int {
if habits.count == 0 {
return 1
} else {
return habits.count
}
}
var count = 0
var perc = 0
for h in habits {
if h.didSports == true {
count += 1
}
}
perc = count * 100 / total
return perc
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
// Headline
Text("This Week")
.bold()
VStack {
Text("Meatfree \(filteredMeat) %")
Text("Sugarfree \(filteredSugar) %")
Text("Sportsrate \(filteredSport)%")
Text("Average Time Loss \(filteredEarlyBird) Min lost")
}
}
}
}
Daily Form:
struct DailyForm: View {
#Environment(\.managedObjectContext) private var viewContext
// #EnvironmentObject var model: HabitModel
#FetchRequest(sortDescriptors: []) var habits: FetchedResults<Habit>
#State var getUpTime = Date()
#State var ateMeat = false
#State var ateSugar = false
#State var didSports = false
var body: some View {
VStack {
HStack {
Button("Clear") {
clear()
}
Spacer()
Button("Add") {
addHabit()
clear()
}
}
.padding()
ScrollView (showsIndicators: false) {
VStack (alignment: .leading) {
DatePicker("Get up Time", selection: $getUpTime, displayedComponents: .hourAndMinute)
Toggle("Ate Meat?", isOn: $ateMeat)
Toggle("Ate Sugar?", isOn: $ateSugar)
Toggle("Did Sports?", isOn: $didSports)
}
.padding(.horizontal)
}
}
}
func clear() {
getUpTime = Date()
ateMeat = false
ateSugar = false
didSports = false
}
func addHabit() {
let habit = Habit(context: viewContext)
habit.id = UUID()
habit.getUpTime = getUpTime
habit.ateMeat = ateMeat
habit.ateSugar = ateSugar
habit.didSports = didSports
do {
try viewContext.save()
}
catch {
// Couldn't save the recipe
}
}
}

Related

Ag-grid infinite model pagination server-side

I'm attempting to use ag-grid with server side pagination. I updated the code sample from the ag-grid website ( below ). I retrieve the columnDefs in the ngOnInit method but alas neither the columnHeaders appear nor the rowdata. I can debug into the GetRows function and see that the rows are coming back. The total number of records gets set correctly.
If anyone can see why the grid's not showing the columns/rows I'd really appreciate it.
This is the output in the console.
ag-Grid.RowNodeBlockLoader: printCacheStatus: activePageLoadsCount = 0, blocks = {"0":{"blockNumber":0,"startRow":0,"endRow":10,"pageStatus":"loaded"}}
ag-Grid.RowNodeBlockLoader: checkBlockToLoad: no pages to load
ag-Grid.InfiniteCache: onPageLoaded: page = 0, lastRow = 5
but while the total number of records is returned from the call and sets
import { Component, OnInit, Input } from '#angular/core';
import {TableMetadata} from "../model/table-metadata";
import { HttpClient } from "#angular/common/http";
import { GridOptions } from "ag-grid";
import { BrxTableService } from '../service/brx-table.service';
#Component({
selector: 'app-brx-delta-agrid',
// templateUrl: './brx-delta-agrid.component.html',
template: `<ag-grid-angular
#agGrid
style="width: 100%; height: 100%;"
id="myGrid"
class="ag-theme-balham"
[columnDefs]="columnDefs"
[components]="components"
[floatingFilter]="true"
[debug]="true"
[enableServerSideSorting]="true"
[enableServerSideFilter]="true"
[enableColResize]="true"
[rowSelection]="rowSelection"
[rowDeselection]="true"
[rowModelType]="rowModelType"
[paginationPageSize]="paginationPageSize"
[cacheOverflowSize]="cacheOverflowSize"
[maxConcurrentDatasourceRequests]="maxConcurrentDatasourceRequests"
[infiniteInitialRowCount]="infiniteInitialRowCount"
[maxBlocksInCache]="maxBlocksInCache"
[pagination]="true"
[cacheBlockSize]="cacheBlockSize"
[getRowNodeId]="getRowNodeId"
(gridReady)="onGridReady($event)"
></ag-grid-angular>
`,
styleUrls: ['./brx-delta-agrid.component.css'],
providers: [BrxTableService]
})
export class BrxDeltaAgridComponent implements OnInit{
public state = {
skip: 0,
take: 5
};
private columnDefs = [];
private gridApi;
private gridColumnApi;
private components;
private rowSelection;
private rowModelType;
private paginationPageSize;
private cacheBlockSize;
private cacheOverflowSize;
private maxConcurrentDatasourceRequests;
private infiniteInitialRowCount;
private maxBlocksInCache;
private getRowNodeId;
#Input('tableMetadata') tableMetadata:TableMetadata;
constructor(private http: HttpClient, private brxTableService:BrxTableService) {
this.components = {
loadingRenderer: function(params) {
if (params.value !== undefined) {
return params.value;
} else {
return '<img src="../assets/loading.gif">';
}
}
};
this.rowSelection = "multiple";
this.rowModelType = "infinite";
this.paginationPageSize = 10;
this.cacheBlockSize = 10;
this.cacheOverflowSize = 2;
this.maxConcurrentDatasourceRequests = 2;
this.infiniteInitialRowCount = 1;
this.maxBlocksInCache = 2;
this.getRowNodeId = function(item) {
return item.R_ID;
};
}
ngOnInit() {
this.columnDefs = this.getColumnDefs();
}
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
this.http
.get("http://localhost:8080/api/"+ this.tableMetadata.tableName)
.subscribe(data => {
data._embedded[this.tableMetadata.tableName +"s"].forEach(function(data, index) {
data.R_ID = "R" + (index + 1);
});
var dataSource = {
rowCount: null,
getRows: function(params) {
console.log("asking ford " + params.startRow + " to " + params.endRow);
setTimeout(function() {
let collectionName ='';
for (var property in data._embedded) {
if (property.startsWith("BRX")) {
collectionName = property;
}
}
var dataAfterSortingAndFiltering = sortAndFilter(data._embedded[collectionName], params.sortModel, params.filterModel);
var rowsThisPage = dataAfterSortingAndFiltering.slice(params.startRow, params.endRow);
var lastRow = 5; // data.page.totalElements;
// if (dataAfterSortingAndFiltering.length <= params.endRow) {
// lastRow = dataAfterSortingAndFiltering.length;
// }
params.successCallback(rowsThisPage, lastRow);
}, 500 );
}
};
params.api.setDatasource(dataSource);
});
}
public getColumnDefs() {
let columnDefs = [];
for (let i=0; i<this.tableMetadata.columnNames.length; i++) {
let columnName = this.tableMetadata.columnNames[i];
let columnDef = {
headerName: columnName,
field: columnName,
width:100
};
columnDefs.push(columnDef);
}
return columnDefs;
}
}
function sortAndFilter(allOfTheData, sortModel, filterModel) {
return sortData(sortModel, filterData(filterModel, allOfTheData));
}
function sortData(sortModel, data) {
var sortPresent = sortModel && sortModel.length > 0;
if (!sortPresent) {
return data;
}
var resultOfSort = data.slice();
resultOfSort.sort(function(a, b) {
for (var k = 0; k < sortModel.length; k++) {
var sortColModel = sortModel[k];
var valueA = a[sortColModel.colId];
var valueB = b[sortColModel.colId];
if (valueA == valueB) {
continue;
}
var sortDirection = sortColModel.sort === "asc" ? 1 : -1;
if (valueA > valueB) {
return sortDirection;
} else {
return sortDirection * -1;
}
}
return 0;
});
return resultOfSort;
}
function filterData(filterModel, data) {
var filterPresent = filterModel && Object.keys(filterModel).length > 0;
if (!filterPresent) {
return data;
}
var resultOfFilter = [];
for (var i = 0; i < data.length; i++) {
var item = data[i];
if (filterModel.age) {
var age = item.age;
var allowedAge = parseInt(filterModel.age.filter);
if (filterModel.age.type == "equals") {
if (age !== allowedAge) {
continue;
}
} else if (filterModel.age.type == "lessThan") {
if (age >= allowedAge) {
continue;
}
} else {
if (age <= allowedAge) {
continue;
}
}
}
if (filterModel.year) {
if (filterModel.year.values.indexOf(item.year.toString()) < 0) {
continue;
}
}
if (filterModel.country) {
if (filterModel.country.values.indexOf(item.country) < 0) {
continue;
}
}
resultOfFilter.push(item);
}
return resultOfFilter;
}
style="width: 100%; height: 100%;"
Hi folks, facepalm time... The height here was set to 100%. The table was located in an overlay that had a width of zero at the time of rendering so the rows and column headers never rendered.
I still can't get continuous server requests happening with the pagination but at least i can see the data :)
Hope this example helps someone because I couldn't find many examples online.
Thanks,
Mark.

Typescript and angular 2

import { Injectable } from '#angular/core';
import { Grocery } from '../../auth/grocery.model';
export interface CartItem {
grocery: Grocery;
count: number;
amount: number;
}
export class Cart {
count: number = 0;
amount: number = 0;
items: CartItem[] = [];
}
#Injectable()
export class CartService {
cart: Cart = new Cart();
constructor(){}
/* constructor(private Cart: Cart) {
this.cart = Cart;
}*/
addGrocery(grocery: Grocery) {
console.log(this.cart);
console.log("gro" + grocery);
console.log(grocery.sno);
let item: CartItem = this.findItem(grocery.sno);
console.log("first" + item);
if (item) {
item.count++;
item.amount += grocery.cost;
console.log("item" + item.amount);
} else {
item = {
grocery: grocery,
count: 1,
amount: grocery.cost
};
console.log("else" + this.cart.items.push(item));
this.cart.items.push(item);
}
this.cart.count++;
this.cart.amount += grocery.cost;
console.log("cart" + this.cart.amount);
console.log(item);
console.log(this.cart);
return item;
}
removeProduct(grocery: Grocery) {
let item: CartItem = this.findItem(grocery.sno);
if (item) {
item.count--;
item.amount -= grocery.cost;
if (!item.count) {
this.remove(item);
}
this.cart.count--;
this.cart.amount -= grocery.cost;
}
return item;
}
removeItem(item: CartItem) {
this.remove(item);
this.cart.count -= item.count;
this.cart.amount -= item.amount;
}
findItem(id: string): CartItem {
for (let i = 0; i < this.cart.items.length; i++) {
if (this.cart.items[i].grocery.sno === id) {
return this.cart.items[i];
}
}
return null;
}
clearCart() {
this.cart.items = [];
this.cart.amount = 0;
this.cart.count = 0;
}
remove(item: CartItem) {
let indx: number = this.cart.items.indexOf(item);
if (indx !== -1) {
this.cart.items.splice(indx, 1);
}
}
}
when calling the cart variable from another component the cart is showing empty and the values are not incremented.
addGrocery(grocery: Grocery) {
console.log(this.cart);
console.log("gro" + grocery);
console.log(grocery.sno);
let item: CartItem = this.findItem(grocery.sno);
console.log("first" + item);
if (item) {
item.count++;
item.amount += grocery.cost;
console.log("item" + item.amount);
} else {
item = {
grocery: grocery,
count: 1,
amount: grocery.cost
};
console.log("else" + this.cart.items.push(item));
this.cart.items.push(item);
}
this.cart.count++;
this.cart.amount += grocery.cost;
console.log("cart" + this.cart.amount);
console.log(item);
console.log(this.cart);
return item;
}
In the above code the increment is being done
but in the below code it's showing initial values when calling cart from another component
#Injectable()
export class CartService {
cart: Cart = new Cart();
constructor(){}

nodejs async how to set callback

I have the following piece of code which is working fine.
var config = require('./config');
var cheerio = require('cheerio');
var myhttp = require('./myHttp');
var stringHelper = require('./stringHelper');
var Base64 = require('./base64.js').Base64;
var Encrypt = require('./Encrypt.js');
var myEncode = require('./Encode.js');
var rules = require('./rules');
var io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379 });
var mysql = require('mysql');
delete require.cache[require.resolve('./requestLogin1.js')]
var myvar = require('./requestLogin1.js');
var connection = mysql.createConnection(
{
host : 'localhost',
user : 'root',
password : 'abc',
database : 'abcd'
}
);
connection.connect(function(err) {
if (err) {
console.log('error connecting: ' + err.stack);
return;
}
});
var timerOB;
var timerMW;
var timerP;
var timerTL;
var news = {
'mw': [],
'ob': [],
'all': {},
};
var status = false;
function round(rnum, rlength) {
return newnumber = Math.round(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
}
function roundup(rnum, rlength) {
return newnumber = Math.ceil(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
}
function rounddown(rnum, rlength) {
return newnumber = Math.floor(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
}
function function1(_html) {
console.log('function1 run')
var $ = cheerio.load(_html);
var v_lgnid = $('#userId').attr('value');
var v_psswrd = config.password;
var v_data = v_lgnid + "|" + v_psswrd;
var _key = $('#accntid').attr('value');
if (_key) {
v_data = Base64.encode(Encrypt.AESEncryptCtr(v_data, _key , "256"));
v_data = escape(v_data);
myhttp.get(
'https://example.com/ValidPassword.jsp?' + $('#name').attr('value') + "=" + v_data,
function (_htmlShowImage) {
if (_htmlShowImage && _htmlShowImage.trim() == "OK") {
function2();
} else {
console.log('Login Fail');
}
});
} else {
login();
console.log('Encrypt password error');
}
}
function function2() {
myhttp.get(
'https://example.com/QuestionsAuth.jsp',
function (_htmlShowImage) {
var $ = cheerio.load(_htmlShowImage);
var sLoginID = $('#sLoginID').attr('value');
var Answer1 = config.answer1;
var Answer2 = config.answer2;
var Index1 = $('#st1').attr('value');
var Index2 = $('#st2').attr('value');
var v_data = sLoginID + "|" + Answer1 + "|" + Answer2 + "|" + Index1 + "|" + Index2;
v_data = Base64.encode(Encrypt.AESEncryptCtr(v_data, $('#key_questauth').attr('value'), "256"));
v_data = escape(v_data);
myhttp.get(
'https://example.com/ValidAnswers.jsp?' + $('#name_questauth').attr('value') + "=" + v_data,
function (_htmlShowImage) {
if (_htmlShowImage && _htmlShowImage.trim() == "OK") {
//rootCallback();
myhttp.get(
'https://example.com/DefaultLogin.jsp',
function (_html) {
console.log('Login sucess')
stringHelper.SaveFileCookies('abcd.txt', myhttp.loadCookie(), 'save cookie login sucess');
if (timerMW) {
clearTimeout(timerMW);
}
timerMW = setTimeout(function6, config.DelayExtractMW);
if (timerOB) {
clearTimeout(timerOB);
}
timerOB = setTimeout(function5, config.DelayExtractOB);
if (timerP) {
clearTimeout(timerP);
}
timerP = setTimeout(function4, config.function4);
});
} else {
console.log('Login Fail - timer');
}
});
});
}
var login = function () {
if (timerMW) {
clearTimeout(timerMW);
}
if (timerOB) {
clearTimeout(timerOB);
}
if (timerP) {
clearTimeout(timerP);
}
if (timerTL) {
clearTimeout(timerTL);
}
myhttp.init();
myhttp.post(
'https://example.com/ShowImage.jsp',
{ "requiredLogin": myEncode.Convert(config.uname) },
function (_htmlpost) {
if (_htmlpost) {
function1(_htmlpost);
} else {
if (timerTL) {
clearTimeout(timerTL);
}
timerTL = setTimeout(login, config.DelayNestError);
}
});
}
exports.login = login;
function function3() {
return {
TS: '',
MWP: 0,
LTP: 0,
NQ: 0,
OBBP: '',
OBSP: '',
CurrTime: 0,
rules: {}
};
}
function function4() {
status = false;
myhttp.get('https://example.com/PB.jsp?Exchange=',
function (_html) {
if (_html && _html.length > 10) {
news.pn = {};
$ = cheerio.load(_html);
$('tr[id^="TR"]').each(function () {
status = true;
var symbol = $('td:nth-child(3)', this).text().trim();
var objob = {
'NQ': parseInt($('td:nth-child(11)', this).text().trim()),
};
var post = {
'symbol': symbol,
'nq': objob.NQ
};
connection.query('INSERT INTO NP SET ?', post, function (err,result){
if (err)
{console.log("NP sql insert error : " +symbol);}
else {
console.log("data inserted into NP Table : " +symbol);
}
});
var objstock = news.all[symbol];
if (typeof objstock!='undefined') {
objstock.NQ = objob.NQ;
news.pn[symbol] = objob;
news.all[symbol] = objstock;
if (status) {
io.emit('news', news);
}
}
else
{
console.log('symbol not found');
}
});
if (timerP) {
clearTimeout(timerP);
}
console.log('setTimer function4:' + config.DelayExtractPn);
timerP = setTimeout(function4, config.DelayExtractPn);
}
connection.query('UPDATE MASTER1 SET tbq = (SELECT sum(a.bq) FROM (select distinct symbol, bq from NP) as a)', function (err,result){
if (err)
{console.log("CQ06 skipped: ");}
else {
console.log("Step 6 - Master1 tbq data updated");
}
});
connection.query('UPDATE MASTER1 SET tsq = (SELECT sum(a.sq) FROM (select distinct symbol, sq from NP) as a)', function (err,result){
if (err)
{console.log("CQ07 skipped: ");}
else {
console.log("Step 7 - Master1 tsq data updated");
}
});
});
}
function function5() {
status = false;
myhttp.get('https://example.com/OB.jsp?Exchange=&OrderType=All',
function (_html) {
if (_html && _html.length > 10) {
$ = cheerio.load(_html);
console.log('OB - Step 2 - html loaded for parsing');
news.ob = [];
$('tr[id^="TR"]').each(function () {
var statusOrder = $('td:nth-child(20)', this).text().trim();
if (statusOrder.toLowerCase().indexOf('open') >= 0) {
status = true;
var objob = {
'symbol': $('td:nth-child(6)', this).text().trim(),
'buysell': $('td:nth-child(9)', this).text().trim(),
'ordernumber': $('input[name="Select"]', this).attr('value'),
};
var objstock = news.all[objob.symbol];
objstock.OBBP = objob.buysell == "BUY"?objob.ordernumber:"";
objstock.OBSP = objob.buysell == "SELL"?objob.ordernumber:"";
news.ob.push(objob);
}
});
if (status) {
io.emit('news', news);
}
if (timerOB) {
clearTimeout(timerOB);
}
timerOB = setTimeout(function5, config.DelayExtractOB);
}
});
}
function function6() {
myhttp.get(
'https://example.com/MW.jsp?',
function (_html) {
if (_html && _html.length > 10) {
var $ = cheerio.load(_html);
status = false;
news.mw = [];
var countCheckRule = 0;
var countCheckedRule = 0;
var tmpall = {};
$('tr[onclick]').each(function () {
status = true;
var data1 = $("input[onclick*='Apply(']", this).attr('onclick');
var arrdata1 = data1.split("','");
var stockid = arrdata1[1].split('|')[0];
var symbol = $('td:nth-child(3)', this).text().trim();
var price = parseFloat($('td:nth-child(4)', this).text().trim());
var cTime = stringHelper.getIndiaTime();
var CurrTime = cTime.toLocaleTimeString();//(will be updated every 60 seconds)
news.mw.push({
'symbol': symbol,
'price': price,
'stockid': stockid,
'CurrTime': CurrTime,
});
var objstock = news.all[symbol];
if (!objstock) {
objstock = function3();
}
if (!news.pn[symbol]) {
objstock.NQ = 0;
}
var notfoundob = true;
for (var symbolkey in news.ob) {
if (news.ob[symbolkey].symbol == symbol) {
notfoundob = false;
}
}
if (notfoundob) {
objstock.OBBP = "";
objstock.OBSP = "";
}
objstock.TS = symbol;//trade symbol
objstock.MWP = stockid;//trade id
objstock.LTP = price;
objstock.CurrTime = CurrTime;
rules.checRules(objstock, myhttp, function (rules_res) {
objstock.rules = rules_res;
tmpall[symbol] = objstock;
});
countCheckRule++;
});
rules.rule12(tmpall, function (_tmpall) {
tmpall = _tmpall;
});
news.all = tmpall;
if (!status) {
login();
console.log('MW - Step 9 - logged out');
} else {
io.emit('news', news);
if (timerMW) {
clearTimeout(timerMW);
}
timerMW = setTimeout(function6, config.DelayExtractMW);
}
} else {
if (timerMW) {
clearTimeout(timerMW);
}
timerMW = setTimeout(function6, config.DelayExtractMW);
}
});
}
Now i want to use async to ensure that function6 is run only after function4 & function5 is run.
I have tried to learn about async from various forums and have changed the code as follows:
var async = require('async'); //line added
// change made
async.parallel([
function function4(callback) {
status = false;
myhttp.get('https://example.com/PB.jsp?Exchange=',
function (_html) {
if (_html && _html.length > 10) {
news.pn = {};
$ = cheerio.load(_html);
$('tr[id^="TR"]').each(function () {
status = true;
var symbol = $('td:nth-child(3)', this).text().trim();
var objob = {
'NQ': parseInt($('td:nth-child(11)', this).text().trim()),
};
console.log('Posn - Step 3A - Found position:' + symbol);
var post = {
'symbol': symbol,
'nq': objob.NQ
};
connection.query('INSERT INTO NP SET ?', post, function (err,result){
if (err)
{console.log("NP sql insert error : " +symbol);}
else {
console.log("data inserted into NP Table : " +symbol);
}
});
var objstock = news.all[symbol];
if (typeof objstock!='undefined') {
objstock.NQ = objob.NQ;
news.pn[symbol] = objob;
news.all[symbol] = objstock;
if (status) {
io.emit('news', news);
}
}
else
{
console.log('symbol not found');
}
});
if (timerP) {
clearTimeout(timerP);
}
console.log('setTimer function4:' + config.DelayExtractPn);
timerP = setTimeout(function4, config.DelayExtractPn);
}
connection.query('UPDATE MASTER1 SET tbq = (SELECT sum(a.bq) FROM (select distinct symbol, bq from NP) as a)', function (err,result){
if (err)
{console.log("CQ06 skipped: ");}
else {
console.log("Step 6 - Master1 tbq data updated");
}
});
connection.query('UPDATE MASTER1 SET tsq = (SELECT sum(a.sq) FROM (select distinct symbol, sq from NP) as a)', function (err,result){
if (err)
{console.log("CQ07 skipped: ");}
else {
console.log("Step 7 - Master1 tsq data updated");
}
});
callback(); //line added
});
},
function function5(callback) {
status = false;
myhttp.get('https://example.com/OB.jsp?Exchange=&OrderType=All',
function (_html) {
if (_html && _html.length > 10) {
$ = cheerio.load(_html);
console.log('OB - Step 2 - html loaded for parsing');
news.ob = [];
$('tr[id^="TR"]').each(function () {
var statusOrder = $('td:nth-child(20)', this).text().trim();
if (statusOrder.toLowerCase().indexOf('open') >= 0 || statusOrder.toLowerCase().indexOf('trigger pending') >= 0) {
status = true;
var objob = {
'symbol': $('td:nth-child(6)', this).text().trim(),
'buysell': $('td:nth-child(9)', this).text().trim(),
'ordernumber': $('input[name="Select"]', this).attr('value'),
};
var objstock = news.all[objob.symbol];
objstock.OBBP = objob.buysell == "BUY"?objob.ordernumber:"";
objstock.OBSP = objob.buysell == "SELL"?objob.ordernumber:"";
news.ob.push(objob);
}
});
if (status) {
console.log('OB - Step 5 - pushed to html page');
io.emit('news', news);
}
if (timerOB) {
clearTimeout(timerOB);
}
timerOB = setTimeout(function5, config.DelayExtractOB);
}
callback(); //line added
});
}
],
function function6() {
myhttp.get(
'https://example.com/MW.jsp?',
function (_html) {
if (_html && _html.length > 10) {
var $ = cheerio.load(_html);
status = false;
news.mw = [];
var countCheckRule = 0;
var countCheckedRule = 0;
var tmpall = {};
$('tr[onclick]').each(function () {
status = true;
var data1 = $("input[onclick*='Apply(']", this).attr('onclick');
var arrdata1 = data1.split("','");
var stockid = arrdata1[1].split('|')[0];
var symbol = $('td:nth-child(3)', this).text().trim();
var price = parseFloat($('td:nth-child(4)', this).text().trim());
var cTime = stringHelper.getIndiaTime();
var CurrTime = cTime.toLocaleTimeString();//(will be updated every 60 seconds)
news.mw.push({
'symbol': symbol,
'price': price,
'stockid': stockid,
'CurrTime': CurrTime,
});
var objstock = news.all[symbol];
if (!objstock) {
objstock = function3();
}
if (!news.pn[symbol]) {
objstock.NQ = 0;
}
var notfoundob = true;
for (var symbolkey in news.ob) {
if (news.ob[symbolkey].symbol == symbol) {
notfoundob = false;
}
}
if (notfoundob) {
objstock.OBBP = "";
objstock.OBSP = "";
}
objstock.TS = symbol;//trade symbol
objstock.MWP = stockid;//trade id
objstock.LTP = price;
objstock.CurrTime = CurrTime;
rules.checRules(objstock, myhttp, function (rules_res) {
objstock.rules = rules_res;
tmpall[symbol] = objstock;
});
countCheckRule++;
});
//new check rules
rules.rule12(tmpall, function (_tmpall) {
tmpall = _tmpall;
});
news.all = tmpall;
if (!status) {
login();
} else {
io.emit('news', news);
if (timerMW) {
clearTimeout(timerMW);
}
timerMW = setTimeout(function6, config.DelayExtractMW);
}
} else {
if (timerMW) {
clearTimeout(timerMW);
}
timerMW = setTimeout(function6, config.DelayExtractMW);
}
});
});
Since my original functions do not have any callback, and since async needs callback, i have tried to code a callback in function4 & function5 - but I guess i have not coded it correctly.
I am getting an error in the line where callback is present that states "TypeError: undefined is not a function".
How do i correct this?
Related Question No. 2 : the current code has a timer function whereby function4, function5 and function6 runs with a preset timer. If async works, how do i define a timer whereby the combined set of function4,5 & 6 works based on a preset timer?
Sorry about the long code -- i am new to nodejs and was handed over this code as such and am trying to get this change made.
Thanks for your guidance.
You can instead make function4 and function5 to return promise and then execute function6 only after both function4's and function5's promise gets resolved.

Check if string is a valid double value in Swift

In Swift, how can one check if a string is a valid double value? I have been using the following extension from this question (but as a float) but if the value cannot be converted, it simply returns "0":
extension String {
var doubleValue:Double? {
return (self as NSString).doubleValue
}
}
Ideally, I would like it to return nil so it can be caught in an if-let, like so:
if let i = str.doubleValue {
object.price = i
} else {
// Tell user the value is invalid
}
edit/update: Xcode 11 or later • Swift 5.1 or later
You can use Double initializer init?<S>(_ text: S) where S : StringProtocol to create an instance property on StringProtocol and use it to check if a String or Substring is a valid Double:
extension StringProtocol {
var double: Double? { Double(self) }
var float: Float? { Float(self) }
var integer: Int? { Int(self) }
}
Testing
let str = "2.9"
if let value = str.double {
print(value) // "2.9\n"
} else {
print("invalid input")
}
str.prefix(1).integer // 2
str.suffix(1).integer // 9
It is indeed more efficient not to create a number formatter every time we do a conversion:
extension String {
struct NumFormatter {
static let instance = NumberFormatter()
}
var doubleValue: Double? {
return NumFormatter.instance.number(from: self)?.doubleValue
}
var integerValue: Int? {
return NumFormatter.instance.number(from: self)?.intValue
}
}
Why not let it return false? Or true of course.
extension String {
func isInt() -> Bool {
if let intValue = Int(self) {
return true
}
return false
}
func isFloat() -> Bool {
if let floatValue = Float(self) {
return true
}
return false
}
func isDouble() -> Bool {
if let doubleValue = Double(self) {
return true
}
return false
}
func numberOfCharacters() -> Int {
return self.characters.count
}
}
Or even better, as suggested by #LeoDabus:
extension String {
var isInteger: Bool { return Int(self) != nil }
var isFloat: Bool { return Float(self) != nil }
var isDouble: Bool { return Double(self) != nil }
}
Here is my function:
func je_numerik(text:Character)->Bool //en znak
{
if((text=="0")||(text=="1")||(text=="2")||(text=="3")||(text=="4")||(text=="5")||(text=="6")||(text=="7")||(text=="8")||(text=="9")){
return true
}
else
{
return false
}
}
func je_stevilka(text: String)->Bool
{
var pika:Character
pika="."
var je_stevilka=true
//var znaki = Character(text)
var znaki=Array(text)
var stevilo_znakov=znaki.count
if(stevilo_znakov==0)
{
je_stevilka=false
}
else
{
if(stevilo_znakov==1)
{
if(je_numerik(znaki[0]))
{
je_stevilka=true
}
else
{
je_stevilka=false
}
}
else
{
if((je_numerik(znaki[0])) && (!((znaki[0]=="0")&&((znaki[1]=="0"))))&&(!((znaki[0]=="0")&&((je_numerik(znaki[1]))))))
{
var je_pika=false
for var i = 0; i < stevilo_znakov; i++
{
if(je_numerik(znaki[i])||(znaki[i]==pika))
{
if(znaki[i]==pika)
{
if(je_pika)
{
je_stevilka=false
}
else
{
je_pika=true
if(stevilo_znakov==(i+1))
{
je_stevilka=false
}
}
}
}
else
{
je_stevilka=false
}
}
}
else
{
je_stevilka=false
}
}
}
return je_stevilka
}
Just call it like this:
var check_if_is_number=je_stevilka(numberText)

I am trying to export rallygrid data in excel file, but getting only headers not values

I am trying to export rallygrid data in excel file, but getting only headers not values.
Below is my code which I wrote to generate grid and export button
From here [https://github.com/andreano/TaskDelta/blob/master/App.js], I stole the export code
prepareChart: function(iteration_data) {
this.converted_values = [];
this.accept_values = [];
this.commit_values = [];
parents = [];
rootParent = this.getContext().getProject().Name;
sortedArray = [];
var project_hash = {}; // project_by_name, with children
Ext.Array.each(iteration_data, function(iteration){
if ((iteration.ProjectName != rootParent && iteration.ChildCount > 0) || iteration.ParentName == rootParent) {
parents.push(iteration.ProjectName);
}
// make a place for me
if ( ! project_hash[iteration.ProjectName] ) { project_hash[iteration.ProjectName] = []; }
// make a place for my parent so it can know children
if ( iteration.ParentName ) {
if ( ! project_hash[iteration.ParentName]) { project_hash[iteration.ParentName] = []; }
project_hash[iteration.ParentName] = Ext.Array.merge( project_hash[iteration.ParentName], iteration.ProjectName);
}
}, this);
// build order this way:
//console.log("Current: ", this.getContext().getProject().Name );
// order the array by parents to children to grandchildren
sortedArray = this._getTreeArray( this.getContext().getProject().Name , project_hash);
parents = Ext.Array.unique(parents);
sortedData = [];
Ext.Array.each(sortedArray, function(name){
Ext.Array.each(iteration_data, function(ite){
if(ite.ProjectName == name) {
sortedData.push(ite);
};
});
});
Ext.Array.each(iteration_data, function(iteration){
if (iteration.ProjectName == rootParent) {
sortedData.push(iteration);
}
}, this);
iteration_data = sortedData;
sprints = [];
teams = [];
this.ratio = {};
for ( var i=0; i<iteration_data.length; i++ ) {
commit_accept_ratio = 0;
var data_point = iteration_data[i];
this.commit_values.push( data_point.Commit );
this.accept_values.push( data_point.Accept );
if ( data_point.Commit > data_point.Accept ) {
this.converted_values.push( data_point.Commit - data_point.Accept );
} else {
this.converted_values.push( 0 );
}
if (data_point.Commit != 0) {
commit_accept_ratio = (data_point.Accept / data_point.Commit ) * 100;
} else {
commit_accept_ratio = 0;
};
sprints.push(iteration_data[i].Name);
teams.push(iteration_data[i].ProjectName);
teams.push(rootParent);
this.ratio[data_point.ObjectID] = commit_accept_ratio;
}
this.sprints = Ext.Array.unique(sprints).sort();
this.teams = Ext.Array.unique(teams);
removable_teams = [];
for ( var i=0; i<this.teams.length; i++ ) {
team_name = null;
var count = 0;
Ext.Array.each(iteration_data, function(data) {
if (this.teams[i] == data.ProjectName && data.Commit == 0 || null || undefined && data.Accept == 0 || null || undefined) {
count += 1;
team_name = data.ProjectName;
}
}, this);
if (count == this.sprints.length) {
removable_teams.push(team_name);
}
}
removable_teams = Ext.Array.unique(removable_teams);
records = [];
recordHash = {};
summaryHash = {};
Ext.Array.each(iteration_data, function(iter) {
if (!recordHash[iter.ProjectName]) {
recordHash[iter.ProjectName] = {
Team: iter.ProjectName,
Name: '4 Sprint Summary',
Commit: [],
Accept: [],
Perc: [],
Summary: 0
};
}
if (!Ext.Array.contains(removable_teams, iter.ProjectName)) {
recordHash[iter.ProjectName]["Commit-" + iter.Name] = iter.Commit;
recordHash[iter.ProjectName]["Accept-" + iter.Name] = iter.Accept;
recordHash[iter.ProjectName]["Perc-" + iter.Name] = this.ratio[iter.ObjectID];
}
}, this);
var summaryArray = Ext.Array.slice( this.sprints, (this.sprints.length - 4))
var iterated_data = [];
Ext.Array.each(summaryArray, function(summ){
Ext.Array.each(iteration_data, function(team) {
if( summ == team.Name){
iterated_data.push(team);
}
});
});
Ext.Array.each(iteration_data, function(summ){
Ext.Array.each(iterated_data, function(team) {
if (!summaryHash[team.ProjectName]) {
summaryHash[team.ProjectName] = {
Commit: 0,
Accept: 0,
Total: 0
};
};
if (!Ext.Array.contains(removable_teams, team.ProjectName)) {
if( summ.ProjectName == team.ProjectName && summ.Name == team.Name) {
summaryHash[team.ProjectName]["Commit"] += summ.Commit;
summaryHash[team.ProjectName]["Accept"] += summ.Accept;
if (summaryHash[team.ProjectName]["Commit"] != 0) {
summaryHash[team.ProjectName]["Total"] = (summaryHash[team.ProjectName]["Accept"] / summaryHash[team.ProjectName]["Commit"] ) * 100;
} else {
summaryHash[team.ProjectName]["Total"] = 0;
};
};
}
});
}, this);
Ext.Object.each(recordHash, function(key, value) {
if (summaryHash[key]) {
value["Summary"] = summaryHash[key].Total;
records.push(value);
}
});
var cfgsValues = [];
cfgsValues.push({text: 'Team', style:"background-color: #D2EBC8", dataIndex: 'Team', width: 170, renderer: function(value, meta_data, record, row, col) {
if (Ext.Array.contains(parents, value)) {
meta_data.style = "background-color: #FFF09E";
return Ext.String.format("<div style='font-weight:bold;text-align:center'>{0}</div>", value);
} else if (rootParent == value){
meta_data.style = "background-color: #CC6699";
return Ext.String.format("<div style='font-weight:bold;text-align:center'>{0}</div>", value);
} else {
return value;
};
}});
cfgsValues.push({text: '4 Sprint Summary', style:"background-color: #D2EBC8", width: 70, dataIndex: 'Summary', renderer: function(value, meta_data, record) {
var color = null;
if (value >= 80 && value <= 120) {
color = "#00AF4F";
}
else if (value >= 60 && value <= 80) {
color = "#FBFE08";
}
else if (value <= 60) {
color = "#FC0002";
}
else if (value >= 120) {
color = "#98CCFB";
};
meta_data.style = "background-color: "+color+"";
return Ext.Number.toFixed(value, 0)+"%";
}});
Ext.Array.each(this.sprints, function(sprint) {
cfgsValues.push(
{text: sprint, style:'background-color:#D2EBC8;text-align:center;font-weight:bold', defaults: {enableColumnHide:false}, columns:[
{text: "Commit", dataIndex: 'Commit-' + sprint, width: 50, renderer: function(value, meta_data, record) {
if( value ) {
return value;
} else {
return "NA";
}
}},
{text: "Accept", dataIndex: 'Accept-' + sprint, width: 60, renderer: function(value, meta_data, record) {
if( value) {
return value;
} else {
return "NA";
}
}},
{text: "%", dataIndex: 'Perc-'+ sprint, width: 50, renderer: function(value, meta_data, record) {
var color = null;
if (value >= 80 && value <= 120) {
color = "#00AF4F";
}
else if (value >= 60 && value <= 80) {
color = "#FBFE08";
}
else if (value <= 60) {
color = "#FC0002";
}
else if (value >= 120) {
color = "#98CCFB";
}
meta_data.style = "background-color: "+color+"";
if (value) {
return Ext.Number.toFixed(value, 0)+"%";
} else {
return "NA";
};
}}
]}
);
});
var chart = Ext.getCmp('mychart');
if (chart) {
chart.destroy();
};
Ext.Array.each(this.sprints, function(sprint) {
Ext.Array.each(records, function(record) {
if (record["Accept-" + sprint] == undefined) {
record["Accept-" + sprint] = undefined;
}
if (record["Commit-" + sprint] == undefined) {
record["Commit-" + sprint] = undefined;
}
if (record["Perc-" + sprint] == undefined) {
record["Perc-" + sprint] = undefined;
}
});
});
this.add({
xtype: 'rallygrid',
id: 'mychart',
store: Ext.create('Rally.data.custom.Store', {
data: records,
pageSize: 100
}),
//viewConfig: {
//stripeRows: false
//},
columnCfgs: cfgsValues,
//columnLines: true
});
this.globalStore = Ext.getCmp('mychart');
console.log("this.globalStore", this.globalStore);
this.down('#grid_box').add(this.globalStore);
//this.setLoading(false);
},
_addPrintButton: function() {
var me = this;
this.down('#print_button_box').add( {
xtype: 'rallybutton',
itemId: 'print_button',
text: 'Export to Excel',
disabled: false,
margin: '20 10 10 0',
region: "right",
handler: function() {
me._onClickExport();
}
});
},
_onClickExport: function () { //using this function to export to csv
var that = this;
if (this.down('#grid_box')){
//Ext.getBody().mask('Exporting Tasks...');
//console.log('inside export');
setTimeout(function () {
var template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-' +
'microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head>' +
'<!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>' +
'{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>' +
'</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}' +
'</table></body></html>';
var base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)));
};
var format = function (s, c) {
return s.replace(/{(\w+)}/g, function (m, p) {
return c[p];
});
};
var table = that.getComponent('grid_box');
//console.log("Exporting table ",table);
var excel_data = '<tr>';
Ext.Array.each(table.getEl().dom.outerHTML.match(/<span .*?x-column-header-text.*?>.*?<\/span>/gm), function (column_header_span) {
excel_data += (column_header_span.replace(/span/g, 'td'));
});
excel_data += '</tr>';
Ext.Array.each(table.getEl().dom.outerHTML.match(/<tr class="x-grid-row.*?<\/tr>/gm), function (line) {
excel_data += line.replace(/[^\011\012\015\040-\177]/g, '>>');
});
//console.log("Excel data ",excel_data);
var ctx = {worksheet: name || 'Worksheet', table: excel_data};
window.location.href = 'data:application/vnd.ms-excel;base64,' + base64(format(template, ctx));
Ext.getBody().unmask();
}, 500);
}else{
console.log("grid_box does not exist");
}
}
There is an example in new AppSDK2 documentation of exporting to CSV.
I also have an example of exporting to CSV in this github repo.

Resources