Twig foreach group by date - symfony

I have a table with football matches called 'matches'. In that table there is a field 'kickoff', which is a datetime-column of the time when the match starts. With the following code I get all the matches out of the table.
$matches = $em->createQueryBuilder()
->select('m')
->from('FootballWcBundle:Matches', 'm')
->addOrderBy('m.kickoff', 'ASC')
->getQuery()
->getResult();
return $this->render('FootballWcBundle:Page:matches.html.twig', array(
'matches' => $matches
));
Now I want to show the matches on the screen grouped by the date.
Like this:
12-12-2014
match1
match2
14-12-2014
match3
match4
match5
Is there a way to let Twig know to group by the kickoff column or is there another way to do this?

You could do that as below:
{% set date = null %}
{% for match in matches %}
{% if date != match.kickoff %}
{% set date = match.kickoff %}
<h3>{{ date }}</h3>
{% endif %}
<p>{{ match.name }}</p>
{% endfor %}
In this way, you set the first date as null, and you iterate all matches and write a 'p' tag with the name (I supposed the match had a name to do the example), and when the date of the matches changes, you write a 'h3' tag with the date of the match. As date is set to null in the first iteration, the first date will be write.

There is a controlled break algorithm that originated from COBOL. It can be used in your case, you would have to rewrite it in TWIG though. I successfully used it in JAVA.
Below is C/C++ implementation of the controlled break algorithm. Take a look and use this principle for your case.
#include <iostream>
#define LMARG " "
#define UNDERLN "=============="
using namespace std;
void displayTable(int table[],short size);
//
// Purpose: Illustrated a controlled break algorithm
// Given an ordered sequence of data members, display with summary
//
int main(void)
{
int table[] = {10,12,12,30,30,30,30,40,55,60,60,60};
displayTable(table,sizeof(table)/sizeof(int));
fflush(stdin);
getchar();
return 0;
}
void displayTable(int table[],short size)
{
int currentKey,lastKey;
int i, categoryCount,groupTotal;
currentKey = lastKey = table[0];
groupTotal = categoryCount = i = 0;
while (i < size)
{
if (currentKey == lastKey)
{
groupTotal += table[i];
categoryCount++;
cout << LMARG << table[i] << endl;
}
else
{
cout << LMARG << UNDERLN << endl;
cout << "Total: " << groupTotal << endl;
cout << "Croup Count: " << categoryCount << endl << endl;
cout << LMARG << table[i] << endl; // start of next group
groupTotal = currentKey,categoryCount = 1;
fflush(stdin);getchar();
}
lastKey = currentKey;
currentKey = table[++i]; // get next key
} // while
cout << LMARG << UNDERLN << endl; // last group summary
cout << "Total: " << groupTotal << endl;
cout << "Croup Count: " << categoryCount << endl << endl;
}

Related

Get length scale factor of STEP CAD file with OpenCASCADE

I am trying to get the length unit conversion factor in OpenCASCADE, when importing a STEP format CAD file. In my test file the entity #184 sets the length to meters and during import will be converted to milimeters used by OpenCASCADE internally by default
...
#184=(
LENGTH_UNIT()
NAMED_UNIT(*)
SI_UNIT($,.METRE.)
);
...
I belive the function below is how it should be done, but no matter what i try the "Length_Unit" STEP entity is not matched, and therefore I can't get the scaling factor.
void step_unit_scaling(std::string const &file_name) {
STEPControl_Reader reader;
reader.ReadFile( file_name.c_str() );
const Handle(Interface_InterfaceModel) Model = reader.Model();
Handle(StepData_StepModel) aSM = Handle(StepData_StepModel)::DownCast(Model);
Standard_Integer NbEntities = Model->NbEntities();
for (int i=1; i<=NbEntities; i++) {
Handle(Standard_Transient) enti = aSM->Entity(i);
if (enti->IsKind (STANDARD_TYPE(StepBasic_LengthMeasureWithUnit))) {
Handle(StepBasic_LengthMeasureWithUnit) MWU = Handle(StepBasic_LengthMeasureWithUnit)::DownCast(enti);
Standard_Real scal_mm = MWU->ValueComponent();
std::cout << " --- !!! MATCH !!! --- scal_mm = " << scal_mm << std::endl;
}
}
}
Does anyone know if this is the correct approach, or if there perhaps is a better way.
If you search for an entity of a given type, you should check the types to find an error. The following line will show the actual entity type.
std::cout << "Entity type " << enti->DynamicType()->Name() << std::endl;
When I play with STEP files here, I see that your STEP line leads to an entity of type StepBasic_SiUnitAndLengthUnit. With this code I can test for some expected SI units:
if (enti->IsKind(STANDARD_TYPE(StepBasic_SiUnitAndLengthUnit)))
{
Handle(StepBasic_SiUnitAndLengthUnit) unit =
Handle(StepBasic_SiUnitAndLengthUnit)::DownCast(enti);
if (unit->HasPrefix() &&
(StepBasic_SiUnitName::StepBasic_sunMetre == unit->Name()) &&
(StepBasic_SiPrefix::StepBasic_spMilli == unit->Prefix()))
{
std::cout << "SI Unit is millimetre." << std::endl;
}
else if (!unit->HasPrefix() &&
(StepBasic_SiUnitName::StepBasic_sunMetre == unit->Name()))
{
std::cout << "SI Unit is metre." << std::endl;
}
else
{
std::cout << "I did not understand that unit..." << std::endl;
}
}

What does this recursion function output?

I'm just starting to learn recursion and I don't understand the output, which is 39493. Could you explain?
struct Node {
int value;
Node* next;
}
head --> 3 --> 9 --> 4 --> NULL
void f4(Node* n) {
if(n == NULL)
return;
if(n->next == NULL)
cout << n->value << “ ”;
else {
cout << n->value << “ ”;
f4(n->next);
cout << n->value << “ ”;
}
}
Your f4 function prints out a linked list of integers, forwards (from the head/root to the tail) and then backwards. It does this because the inner call of f4 within the else clause is surrounded by two cout statements, which will both print the current node's value, adding a stack frame (new execution context with the next node) in between. The last node (the tail) is captured by if(n->next == NULL), and there's only one cout statement in this clause, so the tail only prints once.
I added a main method to illustrate this:
#include <iostream>
using namespace std;
struct Node {
int value;
Node* next;
};
void f4(Node* n) {
// This will never be reached
// except if f4 is called with NULL directly
if(n == NULL)
return;
if(n->next == NULL)
cout << n->value << endl;
else {
cout << n->value << endl;
f4(n->next);
cout << n->value << endl;
}
}
int main() {
cout << "Starting!" << endl;
Node n1 = {1, 0};
Node n2 = {2, &n1};
Node n3 = {3, &n2};
// get pointer to n3 -> n2 -> n1
f4(&n3);
return 0;
}
Output:
Starting!
3
2
1
2
3
To understand the stack frame (recursive call) handling mechanism:
https://www.bottomupcs.com/elements_of_a_process.xhtml.
You might understand it better by adding additional markers to differentiate the cout << n->value << endl on different lines.

Can't delete a pointer in C++

I got this code from a book. When I ran on Visual Studio, it said to switch strcpy() to strcpy_s(), and after I did that, it seems the program terminated at the delete pointer. I tried to run on Dev-C++, and it works fine. Anyone knows why? Thank you.
#include "pch.h"
#include <iostream>
#include <cstring>
int main()
{
cout << "Enter a kind of animal: ";
cin >> animal; // ok if input < 20 chars
ps = animal; // set ps to point to string
cout << ps << "!\n"; // ok, same as using animal
cout << "Before using strcpy():\n";
cout << animal << " at " << (int *)animal << endl;
cout << ps << " at " << (int *)ps << endl;
ps = new char[strlen(animal) + 1]; // get new storage
strcpy_s(ps, sizeof(animal), animal); // copy string to new storage
cout << "After using strcpy():\n";
cout << animal << " at " << (int *)animal << endl;
cout << ps << " at " << (int *)ps << endl;
delete[] ps;
return 0;
}

What is the defined behavior of SQLite when interleaving statements that affect each other?

In SQLite if I prepare a SELECT statement and begin stepping through it, then before the last row of the results is reached I execute another statement that has an effect on the SELECT statement that I am stepping through, what is the expected result?
I can't find anything in the SQLite documentation about what is supposed to happen but it seems like an extremely common case when programming in a multi-threaded environment.
Below is a c++ file that can be compiled and run on Windows to demonstrate the situation.
#include "stdafx.h"
#include "sqlite3.h"
#include <Windows.h>
#include <iostream>
#include <Knownfolders.h>
#include <Shlobj.h>
#include <wchar.h>
#include <comdef.h>
using namespace std;
int exec_sql(sqlite3 *db, const char* sql)
{
char *errmsg;
int result = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
if (result != SQLITE_OK) {
cout << errmsg << endl;
return -1;
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Running jsqltst with SQLite version: ";
cout << sqlite3_libversion();
cout << endl;
PWSTR userhome;
if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Profile, NULL, NULL, &userhome))) {
cout << "Failed getting user home dir\n";
return -1;
}
wcout << "User home: " << userhome << endl;
wchar_t *ws1 = userhome, *ws2 = L"\\test.sqlite";
wstring dbpath_str(ws1);
dbpath_str += wstring(ws2);
_bstr_t dbpath(dbpath_str.c_str());
cout << "DB path: " << dbpath << endl;
sqlite3 *db;
int result = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
if (result != SQLITE_OK) {
cout << sqlite3_errmsg(db) << endl;
return -1;
}
const char * create_stmt = "CREATE TABLE IF NOT EXISTS atable (id INTEGER PRIMARY KEY, name TEXT, number INTEGER);";
if (exec_sql(db, create_stmt) != 0) {
return -1;
}
const char * delete_stmt = "DELETE FROM atable;";
if (exec_sql(db, delete_stmt) != 0) {
return -1;
}
const char * insert_stmt = "INSERT INTO atable (name,number) VALUES ('Beta',77),('Alpha',99);";
if (exec_sql(db, insert_stmt) != 0) {
return -1;
}
sqlite3_stmt* select_ss;
const char * select_stmt = "SELECT * FROM atable;";
result = sqlite3_prepare_v2(db, select_stmt, -1, &select_ss, NULL);
if (result != SQLITE_OK) {
cout << sqlite3_errmsg(db) << endl;
return -1;
}
int i = 0;
boolean gotrow;
do {
result = sqlite3_step(select_ss);
gotrow = result == SQLITE_ROW;
if (gotrow) {
i++;
cout << "I got a row!" << endl;
if (i == 1) {
if (exec_sql(db, insert_stmt) != 0) {
return -1;
}
}
}
} while (gotrow);
cout << "Last result: " << result << ", errstr: " << sqlite3_errstr(result) << endl;
result = sqlite3_finalize(select_ss);
if (result != SQLITE_OK) {
cout << sqlite3_errmsg(db) << endl;
return -1;
}
return 0;
}
SQLite's behaviour for concurrent statements in the same transaction is neither documented nor defined.
As you have seen, newly inserted records might be seen when a SELECT's cursor has not yet reached that part of the table.
However, if SQLite needed to create a temporary result table for sorting or grouping, later changes in the table will not appear in that result.
Whether you have a temporary table or not might depend on decisions made by the query optimizer, so this is often not predictable.
If multiple threads access the same connection, SQLite will lock the DB around each sqlite3_step call.
This prevent data corruption, but you will still have the problem that automatic transaction end when their last active statement ends, and that explicit transaction will fail the COMMIT if there is some other active statement.
Multi-threaded programs are better off using (at least) one connection per thread.

Find a specific element within a vector

I have a class team that contains information for football teams. I need to read in a file and add each unique team to a vector season.
//Loop to determine unique teams
if(season.size() <= 1)
{
season.push_back(new_team);
cout << "First team added!" << endl;
}
vector<team>::iterator point;
point = find(season.begin(), season.end(), new_team);
bool unique_team = (point != season.end());
if(unique_team == true && season.size()>1)
{
season.push_back(new_team);
cout << "New team added!" << endl;
}
cout << "# of Teams: " << season.size() << endl;
system("pause");
Any ideas why this doesn't work? I'm still new to this :-) So feel free to give constructive criticism.
I think your logic may be a little off. There first team should be added when the size of the teams vector is 0. Say your team is a vector of integers an insertTeam function would look something like this.
void Season::insertTeam(int team)
{
if (teams.size() == 0)
{
teams.push_back(team);
cout << "First team " << team << " added!" << endl;
}
else
{
vector<int>::iterator point;
point = find(teams.begin(), teams.end(), team);
bool unique_team = (point == teams.end());
if(unique_team == true && teams.size()>0)
{
teams.push_back(team);
cout << "New team " << team << " added!" << endl;
}
}
}

Resources