问:
HELM: include named template inside tpl .Files.Get fails
structure of folders:

```<code>files
  alertmanager
    rules
      - alertmanager.rules
      - nodes.rules
      ...
templates
  - _helpers.tpl
  - prometheus.yaml
</code>```

files/alertmanager/rules/alertmanager.rules

- name: Alertmanager
  rules:
    - alert: PrometheusAlertmanagerConfigurationReloadFailure
      expr: |
        # Without max_over_time, failed scrapes could create false negatives, see
        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.
        max_over_time(alertmanager_config_last_reload_successful{app_kubernetes_io_name="alertmanager"}[5m]) == 0
      for: 10m
      labels:
        severity: critical
        {{ include _default_rule_labels . }}
      annotations:
        type: Alertmanager
        summary: Prometheus AlertManager configuration reload failure
        description: |
          The error could be caused by recent changes and could be caused by an incorrect configuration of alertmanager template (defined in templates/prometheus.yaml).
          Or it can be caused by incorrect route(s) configuration (typically in argocd/apps/values.yaml)

```
<p><strong>templates/_helpers.tpl</strong></p>
<pre class="lang-yaml prettyprint-override"><code>{{/*
Collect alertmanager rules from files
*/}}
{{- define "alertmanager.rules" -}}
{{- range $path, $_ := .Files.Glob "files/alertmanager/rules/**.rules" }}
{{ tpl ($.Files.Get $path) $ }}
{{- end }}
{{- end }}

{{/*
Set default alert rule labels
*/}}
{{- define "_default_rule_labels" -}}
environment: {{ .Values.environment }}
client: {{ .Values.client }}
cluster: {{ .Values.eks_cluster }}
sla: {{ .Values.sla }}
{{- end }}
</code>```

templates/prometheus.yaml

```<code># ? PROMETHEUS ALERT RULES
serverFiles:
  alerting_rules.yml:
    groups:
      {{- include "alertmanager.rules" . | nindent 14 }}
</code>```

I'm getting the following error when trying to render the prometheus.yaml template:

✗  helm template . -s templates/prometheus.yaml
parse error at (root/templates/prometheus.yaml:15): function "_default_rule_labels" not defined
```

How to approach?

I can render {{ .Values.something }} inside files/alertmanager/rules/alertmanager.rules, but inclusion of named templates throws an error.

Body:
structure of folders:

files
  alertmanager
    rules
      - alertmanager.rules
      - nodes.rules
      ...
templates
  - _helpers.tpl
  - prometheus.yaml

files/alertmanager/rules/alertmanager.rules

- name: Alertmanager
  rules:
    - alert: PrometheusAlertmanagerConfigurationReloadFailure
      expr: |
        # Without max_over_time, failed scrapes could create false negatives, see
        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.
        max_over_time(alertmanager_config_last_reload_successful{app_kubernetes_io_name="alertmanager"}[5m]) == 0
      for: 10m
      labels:
        severity: critical
        {{ include _default_rule_labels . }}
      annotations:
        type: Alertmanager
        summary: Prometheus AlertManager configuration reload failure
        description: |
          The error could be caused by recent changes and could be caused by an incorrect configuration of alertmanager template (defined in templates/prometheus.yaml).
          Or it can be caused by incorrect route(s) configuration (typically in argocd/apps/values.yaml)

templates/_helpers.tpl

{{/*
Collect alertmanager rules from files
*/}}
{{- define "alertmanager.rules" -}}
{{- range $path, $_ := .Files.Glob "files/alertmanager/rules/**.rules" }}
{{ tpl ($.Files.Get $path) $ }}
{{- end }}
{{- end }}

{{/*
Set default alert rule labels
*/}}
{{- define "_default_rule_labels" -}}
environment: {{ .Values.environment }}
client: {{ .Values.client }}
cluster: {{ .Values.eks_cluster }}
sla: {{ .Values.sla }}
{{- end }}

templates/prometheus.yaml

# ? PROMETHEUS ALERT RULES
serverFiles:
  alerting_rules.yml:
    groups:
      {{- include "alertmanager.rules" . | nindent 14 }}

I'm getting the following error when trying to render the prometheus.yaml template:

✗  helm template . -s templates/prometheus.yaml
parse error at (root/templates/prometheus.yaml:15): function "_default_rule_labels" not defined

How to approach?

I can render {{ .Values.something }} inside files/alertmanager/rules/alertmanager.rules, but inclusion of named templates throws an error.


来源: stackexchange

问:
Unable to populate multiple results for the invoice system using MySQL query
I'm trying to build an invoice generator GUI app using tkinter and reportlab. Currently, it's reading an excel file showing some results on treeview. However, to generate an invoice, I am creating a pdf file to show all the data for the invoice but unable to populate multiple results in the pdf file from MySQL table.

Here is my complete code:

```<code>import tkinter as tk
from tkinter import ttk
import pandas as pd
from tkinter import filedialog
import mysql.connector
import os
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle

def browse_file():
    # Open the file browser dialog
    file_path = filedialog.askopenfilename()

    # Read the Excel file into a DataFrame
    df = pd.read_excel("mpo.xlsx", sheet_name='OrderDetails')
    df = df.fillna('NULL')

    # Connect to the MySQL database
    conn = mysql.connector.connect(user='root', password='', host='localhost', database='magnetico')
    cursor = conn.cursor()

    # Insert each row into the MySQL database
    for index, row in df.iterrows():

      cursor.execute("INSERT INTO perorder (mp_task_nr, batch_id, dropoff_sequence, id_user_payout_type, task_status, city, fleet, id_user, Name, Vendor, order_date, UID, KM, total_amount, Remarks) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", (row["mp_task_nr"], row["batch_id"], row["dropoff_sequence"], row["id_user_payout_type"], row["task_status"], row["city"], row["fleet"], row["id_user"], row["Name"], row["Vendor"], row["order_date"], row["UID"], row["KM"], row["total_amount"], row["Remarks"]))

    # Commit the changes and close the cursor and connection
    conn.commit()
    cursor.close()
    conn.close()

def populate_treeview():
    # Connect to the MySQL database
    conn = mysql.connector.connect(user='root', password='', host='localhost', database='magnetico')
    cursor = conn.cursor()

    # Execute a SELECT statement
    cursor.execute("SELECT id_user, Vendor, KM FROM perorder")

    # Fetch the results
    results = cursor.fetchall()

    # Add the results to the Treeview widget
    for result in results:
        treeview.insert("", tk.END, values=result)

    # Close the cursor and connection
    cursor.close()
    conn.close()

def generateInvoice():

  # Connect to the MySQL database
  conn = mysql.connector.connect(user='root', password='', host='localhost', database='magnetico')
  cursor = conn.cursor()

  # Execute a SELECT statement to retrieve the invoice data
  cursor.execute("SELECT city, count(KM), total_amount, total_amount*count(KM), total_amount*count(KM), round(total_amount*count(KM)*0.05,2), total_amount*count(KM)*0.05+(total_amount*count(KM)) FROM perorder where city like '%XB' and KM between 1 and 3")

  # Fetch the results
  results = cursor.fetchall()

  # Create the PDF file
  pdf_file = "invoice.pdf"
  doc = SimpleDocTemplate(pdf_file, pagesize=letter)

  # Create the table data
  table_data = []
  table_data.append(['City', 'Qantity', 'Rate', 'Amount', 'Taxable Value','Amount + 5% VAT', 'Grand Total'])
  for result in results:
    table_data.append([result[0], result[1], result[2], result[3], result[4], result[5], result[6]])

  # Create the table
  table = Table(table_data)

  # Set the table style
  table.setStyle(TableStyle([
      ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
      ('BOX', (0,0), (-1,-1), 0.25, colors.black)
  ]))

  # Build the document
  doc.build([table])

# Create the root window
root = tk.Tk()
root.title("Megnatico Invoice System")
root.geometry("800x800")

# Create the treeview
treeview = ttk.Treeview(root)
treeview.pack(side="left", fill="both", expand=True)

treeview["columns"] = ("id_user", "Vendor", "KM")
treeview.column("id_user", width=150, minwidth=150, stretch=tk.NO)
treeview.column("Vendor", width=150, minwidth=150, stretch=tk.NO)
treeview.column("KM", width=150, minwidth=150, stretch=tk.NO)
treeview.heading("id_user", text="User ID")
treeview.heading("Vendor", text="Vendor")
treeview.heading("KM", text="KM")
treeview["displaycolumns"] = ("id_user", "Vendor", "KM")

# Create the buttons
read_excel_button = tk.Button(root, text="Read Excel", command=browse_file)
invoice_per_order_button = tk.Button(root, text="Invoice per Order", command=populate_treeview)
save_pdf_button = tk.Button(root, text="Generate Invoice", command=generateInvoice)
close_button = tk.Button(root, text="Close")

# Place the buttons in a frame and pack the frame to the right of the root window
button_frame = tk.Frame(root)
button_frame.pack(side="right", fill="both")
read_excel_button.pack(padx=10, pady=5)
invoice_per_order_button.pack(padx=10, pady=5)
save_pdf_button.pack(padx=10, pady=5)
close_button.pack(padx=10, pady=5)

# Run the Tkinter event loop
root.mainloop()
</code>```

From the above code, the following code is populating invoice result:

```<code># Execute a SELECT statement to retrieve the invoice data
cursor.execute("SELECT city, count(KM), total_amount, total_amount*count(KM), total_amount*count(KM), round(total_amount*count(KM)*0.05,2), total_amount*count(KM)*0.05+(total_amount*count(KM)) FROM perorder where city like '%XB' and KM between 1 and 3")
</code>```

Example of data I have

There are multiple cities AUH, DXB but my current SQL query only generating for DXB. I need it should work for AUH and other KM values too such as 1 to 3, 4 to 5 and 6 to 7.

Current Invoice Result

Example of an expected invoice

If you have any further questions, please ask.

ContentLicense: CC BY-SA 4.0

Body:
I'm trying to build an invoice generator GUI app using tkinter and reportlab. Currently, it's reading an excel file showing some results on treeview. However, to generate an invoice, I am creating a pdf file to show all the data for the invoice but unable to populate multiple results in the pdf file from MySQL table.

Here is my complete code:

import tkinter as tk
from tkinter import ttk
import pandas as pd
from tkinter import filedialog
import mysql.connector
import os
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle

def browse_file():
    # Open the file browser dialog
    file_path = filedialog.askopenfilename()

    # Read the Excel file into a DataFrame
    df = pd.read_excel("mpo.xlsx", sheet_name='OrderDetails')
    df = df.fillna('NULL')

    # Connect to the MySQL database
    conn = mysql.connector.connect(user='root', password='', host='localhost', database='magnetico')
    cursor = conn.cursor()

    # Insert each row into the MySQL database
    for index, row in df.iterrows():

      cursor.execute("INSERT INTO perorder (mp_task_nr, batch_id, dropoff_sequence, id_user_payout_type, task_status, city, fleet, id_user, Name, Vendor, order_date, UID, KM, total_amount, Remarks) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", (row["mp_task_nr"], row["batch_id"], row["dropoff_sequence"], row["id_user_payout_type"], row["task_status"], row["city"], row["fleet"], row["id_user"], row["Name"], row["Vendor"], row["order_date"], row["UID"], row["KM"], row["total_amount"], row["Remarks"]))

    # Commit the changes and close the cursor and connection
    conn.commit()
    cursor.close()
    conn.close()

def populate_treeview():
    # Connect to the MySQL database
    conn = mysql.connector.connect(user='root', password='', host='localhost', database='magnetico')
    cursor = conn.cursor()

    # Execute a SELECT statement
    cursor.execute("SELECT id_user, Vendor, KM FROM perorder")

    # Fetch the results
    results = cursor.fetchall()

    # Add the results to the Treeview widget
    for result in results:
        treeview.insert("", tk.END, values=result)

    # Close the cursor and connection
    cursor.close()
    conn.close()

def generateInvoice():

  # Connect to the MySQL database
  conn = mysql.connector.connect(user='root', password='', host='localhost', database='magnetico')
  cursor = conn.cursor()

  # Execute a SELECT statement to retrieve the invoice data
  cursor.execute("SELECT city, count(KM), total_amount, total_amount*count(KM), total_amount*count(KM), round(total_amount*count(KM)*0.05,2), total_amount*count(KM)*0.05+(total_amount*count(KM)) FROM perorder where city like '%XB' and KM between 1 and 3")

  # Fetch the results
  results = cursor.fetchall()

  # Create the PDF file
  pdf_file = "invoice.pdf"
  doc = SimpleDocTemplate(pdf_file, pagesize=letter)

  # Create the table data
  table_data = []
  table_data.append(['City', 'Qantity', 'Rate', 'Amount', 'Taxable Value','Amount + 5% VAT', 'Grand Total'])
  for result in results:
    table_data.append([result[0], result[1], result[2], result[3], result[4], result[5], result[6]])

  # Create the table
  table = Table(table_data)

  # Set the table style
  table.setStyle(TableStyle([
      ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
      ('BOX', (0,0), (-1,-1), 0.25, colors.black)
  ]))

  # Build the document
  doc.build([table])

# Create the root window
root = tk.Tk()
root.title("Megnatico Invoice System")
root.geometry("800x800")

# Create the treeview
treeview = ttk.Treeview(root)
treeview.pack(side="left", fill="both", expand=True)

treeview["columns"] = ("id_user", "Vendor", "KM")
treeview.column("id_user", width=150, minwidth=150, stretch=tk.NO)
treeview.column("Vendor", width=150, minwidth=150, stretch=tk.NO)
treeview.column("KM", width=150, minwidth=150, stretch=tk.NO)
treeview.heading("id_user", text="User ID")
treeview.heading("Vendor", text="Vendor")
treeview.heading("KM", text="KM")
treeview["displaycolumns"] = ("id_user", "Vendor", "KM")

# Create the buttons
read_excel_button = tk.Button(root, text="Read Excel", command=browse_file)
invoice_per_order_button = tk.Button(root, text="Invoice per Order", command=populate_treeview)
save_pdf_button = tk.Button(root, text="Generate Invoice", command=generateInvoice)
close_button = tk.Button(root, text="Close")

# Place the buttons in a frame and pack the frame to the right of the root window
button_frame = tk.Frame(root)
button_frame.pack(side="right", fill="both")
read_excel_button.pack(padx=10, pady=5)
invoice_per_order_button.pack(padx=10, pady=5)
save_pdf_button.pack(padx=10, pady=5)
close_button.pack(padx=10, pady=5)

# Run the Tkinter event loop
root.mainloop()

From the above code, the following code is populating invoice result:

# Execute a SELECT statement to retrieve the invoice data
cursor.execute("SELECT city, count(KM), total_amount, total_amount*count(KM), total_amount*count(KM), round(total_amount*count(KM)*0.05,2), total_amount*count(KM)*0.05+(total_amount*count(KM)) FROM perorder where city like '%XB' and KM between 1 and 3")

Example of data I have

There are multiple cities AUH, DXB but my current SQL query only generating for DXB. I need it should work for AUH and other KM values too such as 1 to 3, 4 to 5 and 6 to 7.

Current Invoice Result

Example of an expected invoice

If you have any further questions, please ask.


问:
Why when running this query the values from prc_sum in the where statement appear to all be 100? (Even though I specified to be different to 100)

I want to see if there is any error on the calculations I made, so I am summing the percentages to ensure they sum to 100. I include a WHERE clause to filter by the values which are different to 100 to see if there is any error, but it doesn't seem to work.

```<code>SELECT
      south/ (south + midwest + northeast + west)*100 AS prc_south,
      west/ (south + midwest + northeast + west)*100 AS prc_west,
      northeast/ (south + midwest + northeast + west)*100 AS prc_northeast,
      midwest/ (south + midwest + northeast + west)*100 AS prc_midwest,
      (south/ (south + midwest + northeast + west)*100)+
      (west/ (south + midwest + northeast + west)*100)+
      (northeast/ (south + midwest + northeast + west)*100)+
      (midwest/ (south + midwest + northeast + west)*100) AS sum_prc
      FROM tutorial.us_housing_units
    WHERE  ((south/ (south + midwest + northeast + west)*100)+
           (west/ (south + midwest + northeast + west)*100)+
           (northeast/ (south + midwest + northeast + west)*100)+
           (midwest/ (south + midwest + northeast + west)*100)) != 100

</code>```

I expected to retrieve values which sum_pcr is not 100. However when I run this it only retrieves values which sum_pcr is 100. >

Body:
I want to see if there is any error on the calculations I made, so I am summing the percentages to ensure they sum to 100. I include a WHERE clause to filter by the values which are different to 100 to see if there is any error, but it doesn't seem to work.

SELECT
      south/ (south + midwest + northeast + west)*100 AS prc_south,
      west/ (south + midwest + northeast + west)*100 AS prc_west,
      northeast/ (south + midwest + northeast + west)*100 AS prc_northeast,
      midwest/ (south + midwest + northeast + west)*100 AS prc_midwest,
      (south/ (south + midwest + northeast + west)*100)+
      (west/ (south + midwest + northeast + west)*100)+
      (northeast/ (south + midwest + northeast + west)*100)+
      (midwest/ (south + midwest + northeast + west)*100) AS sum_prc
      FROM tutorial.us_housing_units
    WHERE  ((south/ (south + midwest + northeast + west)*100)+
           (west/ (south + midwest + northeast + west)*100)+
           (northeast/ (south + midwest + northeast + west)*100)+
           (midwest/ (south + midwest + northeast + west)*100)) != 100

I expected to retrieve values which sum_pcr is not 100. However when I run this it only retrieves values which sum_pcr is 100. >


问:
Is there a way in Vega lite to use different color encodings on a choropleth map, the map has a drop down menu
As stated the map has a drop down menu that changes the display of the map, it selects different columns in the dataset. Ideally I would like to show a different "scheme" for input one and input two or what would also work in my case is to use "reverse" the "scale" encoding to reverse the color scheme for one of the two data columns being loaded

Code extract:

```<code>    {"$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "config": {
    "background":"white",
    "view": {"stroke": "trasparent"}},

  "width": 700,
  "height": 500,

  "data": {
    "url": "https://unpkg.com/world-atlas@1.1.4/world/110m.json",
        "format": {
          "type": "topojson",
          "feature": "countries"}
      },

  "projection": {
    "type": "naturalEarth2"},

  "mark": {
      "type": "geoshape",
      "stroke": "rgb(50, 50, 50)",
      "strokeWidth":0.3},

    "transform": [
      {"calculate":"parseInt(datum.id)", "as":"id_N"},
            {
    "lookup": "id_N",
    "from": {
          "key": "id",
          "fields": ["alpha3", "name"],
          "data": {"url": "data1"}}
          },

        {"lookup": "alpha3",

        "from":{
          "data":{
            "url":"data2"},
            "key": "ISO3",
            "fields":["Vulnerability", "Gain"]
        }
        },
        {"calculate": "datum.Vulnerability", "as": "Climate Vulnerability"},
        {"calculate": "datum.Gain", "as": "Overall Vulnerability Index"},
        {"calculate": "datum[Select]","as": "varSelected"},

      ],

    "params": [
      {"name": "Select",
        "value": "Vulnerability",
        "bind": {
          "input": "select",
          "options": [
            "Climate Vulnerability",
            "Overall Vulnerability Index"]}}],

  "encoding": {

    "color":{
      "field":"varSelected",
      "type":"quantitative",
      "title": null,
      "scale":{
        "scheme": {"name": "turbo", "count":5}
        }
          },

        "tooltip":[
        {"field":"name", "title":"Country"},
        {"field":"varSelected","title":"Score","type":"quantitative"}],

  }

</code>```

Body:
As stated the map has a drop down menu that changes the display of the map, it selects different columns in the dataset. Ideally I would like to show a different "scheme" for input one and input two or what would also work in my case is to use "reverse" the "scale" encoding to reverse the color scheme for one of the two data columns being loaded

Code extract:

    {"$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "config": {
    "background":"white",
    "view": {"stroke": "trasparent"}},

  "width": 700,
  "height": 500,

  "data": {
    "url": "https://unpkg.com/world-atlas@1.1.4/world/110m.json",
        "format": {
          "type": "topojson",
          "feature": "countries"}
      },

  "projection": {
    "type": "naturalEarth2"},

  "mark": {
      "type": "geoshape",
      "stroke": "rgb(50, 50, 50)",
      "strokeWidth":0.3},

    "transform": [
      {"calculate":"parseInt(datum.id)", "as":"id_N"},
            {
    "lookup": "id_N",
    "from": {
          "key": "id",
          "fields": ["alpha3", "name"],
          "data": {"url": "data1"}}
          },

        {"lookup": "alpha3",

        "from":{
          "data":{
            "url":"data2"},
            "key": "ISO3",
            "fields":["Vulnerability", "Gain"]
        }
        },
        {"calculate": "datum.Vulnerability", "as": "Climate Vulnerability"},
        {"calculate": "datum.Gain", "as": "Overall Vulnerability Index"},
        {"calculate": "datum[Select]","as": "varSelected"},

      ],

    "params": [
      {"name": "Select",
        "value": "Vulnerability",
        "bind": {
          "input": "select",
          "options": [
            "Climate Vulnerability",
            "Overall Vulnerability Index"]}}],

  "encoding": {

    "color":{
      "field":"varSelected",
      "type":"quantitative",
      "title": null,
      "scale":{
        "scheme": {"name": "turbo", "count":5}
        }
          },

        "tooltip":[
        {"field":"name", "title":"Country"},
        {"field":"varSelected","title":"Score","type":"quantitative"}],

  }


问:
Power Query sends multiple requests instead of one. How to deal with it?
My code for requesting data is simple. Server returns 404 (and simple message "Broken data") every request except every 10th request. On 10th request server returns 200 (With other simple text "Data from server")
So in power query I found this part of code:

```<code>producer = (val) =>
        let
            result =  Web.Contents(url, [ManualStatusHandling = {404}]) // (1)

            status = Value.Metadata(result)[Response.Status]           // (2)

            actualResult = if status = 404 then null else result       // (3)

        in
           Text.FromBinary(actualResult)
</code>```

`

So, when I run request result (1) is okay. And status (2) is okay. But when line (3) executed - instead of using (1) it resends request and gets wrong result.
I've tried to convert (1) to Binary.Buffer but in this case Value.Metadata gives empty record.

How can I force PQ to send only one request or somehow make it manually. Thanks!

Body:
My code for requesting data is simple. Server returns 404 (and simple message "Broken data") every request except every 10th request. On 10th request server returns 200 (With other simple text "Data from server")
So in power query I found this part of code:

producer = (val) =>
        let
            result =  Web.Contents(url, [ManualStatusHandling = {404}]) // (1)

            status = Value.Metadata(result)[Response.Status]           // (2)

            actualResult = if status = 404 then null else result       // (3)

        in
           Text.FromBinary(actualResult)

`

So, when I run request result (1) is okay. And status (2) is okay. But when line (3) executed - instead of using (1) it resends request and gets wrong result.
I've tried to convert (1) to Binary.Buffer but in this case Value.Metadata gives empty record.

How can I force PQ to send only one request or somehow make it manually. Thanks!


问:
Always treat #nullable enable/disable as error
Presently with our build some assembly classes have the #nullable enable/disable/restore attribute set in some of the source files.

As a way of improving our quality I would like to make the build fail if someone sets this pre-processor directive.

If the project is set to <Nullable>enable</Nullable> or <Nullable>disable</Nullable>, that is fine, but within a class file make it fail.

Is there a way to make this happen or do I just need to go through the source files and resolve them. (But that doesn't stop someone in the future bypassing by doing this again).


问:
Multiple Slideshow Loop not working. html, css, javascript
I have a problem with this multiple slideshow inside a Tab Menu. I´m trying to make a multiple slideshow that cycles automatically in loop and pauses on hover, but I can´t get it to work properly. So far the slideshow only plays once and the looping is not working, once the slideshow gets to the last image, the slideshow container looks "empty". Somehow it only reproduces once and to get it to work again, one most refresh the page.

Please help, and thank you a lot in advance!

/* Tabs */
function mySlides(evt, day) {
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(day).style.display = "block";
  evt.currentTarget.className += " active";
}

var doAnimation = true;
var slideIndex = 0;
showSlides(slideIndex);

function toggleSlides(n) {
  showSlides(slideIndex + n, true);
}
Array.from(document.getElementsByClassName("mySlides")).forEach((mySlide)=> {
  mySlide.addEventListener("mouseover",function() {
    doAnimation = false;
  })
  mySlide.addEventListener("mouseout",function() {
    doAnimation = true;
  });
});
var timer;
function showSlides(n, force) {
  console.log(doAnimation)
  if (doAnimation || force) {
    var i;
    var slides = document.getElementsByClassName("mySlides");
    var dots = document.getElementsByClassName("dot");
    for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";
    }
    slideIndex++;
    if (n) {
      slideIndex = n;
    }
    if (slideIndex > slides.length) {slideIndex = 1}
    for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" active", "");
    }
    slides[slideIndex-1].style.display = "block";
    dots[slideIndex-1].className += " active";
    if (force) {
      clearInterval(timer);
      timer = setInterval(showSlides, 4000);
    }
  }
}
timer = setInterval(showSlides, 4000);```
<pre class="snippet-code-css lang-css prettyprint-override"><code>/* Style Fonts */

  @import url('https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300&display=swap');
body {font-family:'Roboto Condensed', sans-serif;}

/* Body */
p {
  font-weight: 900;
  font-size: 50px;
  text-align: center;
  color: #e84048;
  position: auto;
  margin-top:30px;
}

p.thick {
  font-weight: bold;
  font-size: 20px;
  text-align: center;
  color: #e84048;
  position: absolute;
  top: 10%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

p.thicker {
  font-weight: bold;
  font-size: 20px;
  text-align: center;
  color: #e84048;
  position: absolute;
  bottom: 0%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

/* Title Slide */
h1 {font-family: 'Roboto Condensed', sans-serif;
color: white;
font-size: 3.5rem;
font-weight: bold;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h1 {
        font-size: 2rem;
    }
}

/* Time */
h2 {font-family: 'Roboto Condensed', sans-serif;
color: #e84048;
font-size: 1rem;
position: absolute;
top: 10%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h2 {
        font-size: 1rem;
    }
}

/* Instructor */
h3 {font-family: 'Roboto Condensed', sans-serif;
color: #e84048;
font-size: 1rem;
position: absolute;
bottom:0%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h3 {
        font-size: 1rem;
    }
}

/* Hover Description */
h4 {font-family: 'Roboto Condensed', sans-serif;
color: white;
font-size: 1rem;
position:absolute;
left:50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h4 {
        font-size: 1rem;
    }
}

/* Title Tab */
h5 {font-family: 'Roboto Condensed', sans-serif;
color: #1e0f55;
font-size: 40px;
left: 50%;
position: relative;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
margin-top: 100px;
margin-bottom: 0px;
  }

  /* Subtitle Tab */
h6 {font-family: 'Roboto Condensed', sans-serif;
color: white;
font-size: 25px;
left: 50%;
position: relative;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
margin-top: -10px;
margin-bottom: 0px;
  }

/* Tab Weekend */
.tab {
  overflow: hidden;
  background-color: #e84048;
}

/* Style buttons tab */
.tab button {
  background-color: inherit;
  color: white;
  float: left;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 14px 16px;
  transition: 0.3s;
  font-size: 18px;
  font-family:'Roboto Condensed', sans-serif;
}

/* tab buttons hover */
.tab button:hover {
  background-color: #ff8080;
  color: ##e84048
;
}

/* active tablink class */
.tab button.active {
  background-color: #1e0f55;
  color: #e84048
  ;
}

/* Style tab content */
.tabcontent {
  display: none;
  border: none;
}

/* Slideshow container */

* {
    box-sizing: border-box;
}

.mySlides {
    display: none;
}

img {
      vertical-align: middle;
      height:100%;
   }

/* Number text (1/3 etc) */
.numbertext {
    color: #f2f2f2;
    font-size: 12px;
    padding: 8px 12px;
    position: absolute;
    top: 0;
}

   .slideshow-container {
      width: 100vw;
      height: 80vh;
      position: relative;
   }

.overlay {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  opacity: 0;
  transition: .5s ease-in-out;
  background-color: #1e0f55;
  vertical-align: middle;
  width: 100%;
  height:100%;
}

.slideshow-container:hover .overlay {
  opacity: 0.9;
}

/* dots */
.dot {
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

.active {
  background-color: #717171;
}

/* Fading animation Autorun */
.fade {
    -webkit-animation-name: fade;
    -webkit-animation-duration: 2s;
    animation-name: fade;
    animation-duration: 2s;
}

@-webkit-keyframes fade {
    from {
        opacity: .4
    }

    to {
        opacity: 1
    }
}

@keyframes fade {
    from {
        opacity: .4
    }

    to {
        opacity: 1
    }
}</code>```

Weekend 1

 27.01 - 29.01

  <button class="tablinks" onclick="mySlides(event, 'firstfriday')">Friday</button>
  <button class="tablinks" onclick="mySlides(event, 'firstsaturday')">Saturday</button>
  <button class="tablinks" onclick="mySlides(event, 'firstsunday')">Sunday</button>

>

1 / 3

RETURN TO THE BEGINNING

15:00 -18:00

Theater

Von 15:00 bis 18:00 Uhr

RETURN TO THE BEGINNING
open rehearsal

Although the work is still in progress, with a premiere scheduled for the end of spring 2023, we have decided to share our work in progress, thanking you in advance for your reflections on the subject.
Three survivors in a cave, inside an old mine, amuse themselves resurrecting possible lives of angels and demons, gods and goddesses in search of a lost truth. None of them lived be-fore the disaster. Who is the son or sister of whom? They don’t even know. They don’t dare to leave the cave or maybe they do...?

Residui Teatro and CAAE

2 / 3

Mehr Impulse

22:00 - 23:00

Music

22:00 - 23:00

Mehr Impulse
Alle Infos - bald hier!

Mehr Impulse

3 / 3

Alle Infos - bald hier!

Uhrzeit

Art der Veranstaltung

...

Alle Infos - bald hier!

...

Friday 27.01.23

1 / 3

THE DANCING ACTOR

10:00 -13:00

Oeffentliche Workshop

Von 10:00 bis 13:00 Uhr

THE DANCING ACTOR

klassischem indischen Tanztheater im Bharata Natyam Stil.Die Teilnehmer werden durch das Ueben und Studieren der Grundelemente des Tanzes, von den Grundschritten bis zu den ersten Prinzipien des Schauspiels, in den Tanz eingefuehrt.
Der Workshop hat einen Umfang von 10h und findet auf Englisch, sowie wenn
nötig mit Übersetzung statt.

mit Caterina Scotti
von Teatro Tascabile di Bergamo

2 / 3

THE DANCING ACTOR

15:00 - 18:00

Oeffentliche Workshop

Von 15:00 bis 18:00 Uhr

THE DANCING ACTOR

klassischem indischen Tanztheater im Bharata Natyam Stil.Die Teilnehmer werden durch das Ueben und Studieren der Grundelemente des Tanzes, von den Grundschritten bis zu den ersten Prinzipien des Schauspiels, in den Tanz eingefuehrt.
Der Workshop hat einen Umfang von 10h und findet auf Englisch, sowie wenn
nötig mit Übersetzung statt.

mit Caterina Scotti
von Teatro Tascabile di Bergamo

3 / 3

Green Clouds
Vapour

22:30 - 23:00

Music

Von 22:30 bis 23:00 Uhr

Vapour is an electro acoustic live performance. A viridescent entity dissolving into heavy storms, gently raining down onto the virtual stage. By creating a fog of synthetic sound objects, we enter the world of a wondrous dormant terrain. Sonic material is composed of mineral vibration and reverberating particles
to form low - pitched holograms, placed in an artificial space. Scanning the green void,
palpating moist textures, observing ambiguous matter, leads to confusing diffusing fading decay. Exhaling misty thoughts, spreading a languid feeling of inertia.

Green Clouds
(David Synth)

Saturday 28.01.23

1 / 3

Beconscious

14:00

Oeffentliche Workshop

Um 14:00 Uhr

Beconscious

In diesem Workshop werden wir mit unseren Körpern und der Beziehung zwischen ihnen spielen, während wir den Prozess in Stille und mit Wohlwollen mental beobachten. Dies geschieht insbesondere durch Techniken des Theaters der Forschung, einem von der Gruppe eingeführten theatralischen Weg. Ziel ist es, als Einheit, aber auch als Ganzes, offener und bewusster an unseren Handlungsort zurückzukehren.
Der Workshop hat einen Umfang von 4h und findet auf Englisch, sowie wenn nötig mit Übersetzung statt.

mit der Multiactive Group
der Art Fabrica Athen

2 / 3

THE DANCING ACTOR

15:00 -18:00

Oeffentliche Workshop

Von 15:00 bis 18:00 Uhr

THE DANCING ACTOR

klassischem indischen Tanztheater im Bharata Natyam Stil.Die Teilnehmer werden durch das Ueben und Studieren der Grundelemente des Tanzes, von den Grundschritten bis zu den ersten Prinzipien des Schauspiels, in den Tanz eingefuehrt.
Der Workshop hat einen Umfang von 10h und findet auf Englisch, sowie wenn
nötig mit Übersetzung statt.

mit Caterina Scotti
von Teatro Tascabile di Bergamo

3 / 3

Meg Ella

22:00 -23:00

Music

Von 22:00 bis 23:00 Uhr

Join us for an intimate concert of original songs from Welsh singer songwriter and multi-instrumentalist Meg Ella. With soaring vocals, intricate harmony and cinematic arrangements she will be joined on stage by world class instrumentalists Fraser Bowles (cello) and Nic Jones (trombone).

Marc Almond and Othon Matargas Now based in London, UK, Meg Ella also works as a vocalist, cellist & pianist as a session musician,  arranger and Musical Director for artists, theatre, film and ensembles.

Meg Ella

Sunday 29.01.23

```

Body:
I have a problem with this multiple slideshow inside a Tab Menu. I´m trying to make a multiple slideshow that cycles automatically in loop and pauses on hover, but I can´t get it to work properly. So far the slideshow only plays once and the looping is not working, once the slideshow gets to the last image, the slideshow container looks "empty". Somehow it only reproduces once and to get it to work again, one most refresh the page.

Please help, and thank you a lot in advance!

/* Tabs */
function mySlides(evt, day) {
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(day).style.display = "block";
  evt.currentTarget.className += " active";
}

var doAnimation = true;
var slideIndex = 0;
showSlides(slideIndex);

function toggleSlides(n) {
  showSlides(slideIndex + n, true);
}
Array.from(document.getElementsByClassName("mySlides")).forEach((mySlide)=> {
  mySlide.addEventListener("mouseover",function() {
    doAnimation = false;
  })
  mySlide.addEventListener("mouseout",function() {
    doAnimation = true;
  });
});
var timer;
function showSlides(n, force) {
  console.log(doAnimation)
  if (doAnimation || force) {
    var i;
    var slides = document.getElementsByClassName("mySlides");
    var dots = document.getElementsByClassName("dot");
    for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";
    }
    slideIndex++;
    if (n) {
      slideIndex = n;
    }
    if (slideIndex > slides.length) {slideIndex = 1}
    for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" active", "");
    }
    slides[slideIndex-1].style.display = "block";
    dots[slideIndex-1].className += " active";
    if (force) {
      clearInterval(timer);
      timer = setInterval(showSlides, 4000);
    }
  }
}
timer = setInterval(showSlides, 4000);

/* Style Fonts */

  @import url('https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300&display=swap');
body {font-family:'Roboto Condensed', sans-serif;}

/* Body */
p {
  font-weight: 900;
  font-size: 50px;
  text-align: center;
  color: #e84048;
  position: auto;
  margin-top:30px;
}

p.thick {
  font-weight: bold;
  font-size: 20px;
  text-align: center;
  color: #e84048;
  position: absolute;
  top: 10%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

p.thicker {
  font-weight: bold;
  font-size: 20px;
  text-align: center;
  color: #e84048;
  position: absolute;
  bottom: 0%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

/* Title Slide */
h1 {font-family: 'Roboto Condensed', sans-serif;
color: white;
font-size: 3.5rem;
font-weight: bold;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h1 {
        font-size: 2rem;
    }
}

/* Time */
h2 {font-family: 'Roboto Condensed', sans-serif;
color: #e84048;
font-size: 1rem;
position: absolute;
top: 10%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h2 {
        font-size: 1rem;
    }
}

/* Instructor */
h3 {font-family: 'Roboto Condensed', sans-serif;
color: #e84048;
font-size: 1rem;
position: absolute;
bottom:0%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h3 {
        font-size: 1rem;
    }
}

/* Hover Description */
h4 {font-family: 'Roboto Condensed', sans-serif;
color: white;
font-size: 1rem;
position:absolute;
left:50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;}

@media only screen and (max-width: 450px) {
    h4 {
        font-size: 1rem;
    }
}

/* Title Tab */
h5 {font-family: 'Roboto Condensed', sans-serif;
color: #1e0f55;
font-size: 40px;
left: 50%;
position: relative;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
margin-top: 100px;
margin-bottom: 0px;
  }

  /* Subtitle Tab */
h6 {font-family: 'Roboto Condensed', sans-serif;
color: white;
font-size: 25px;
left: 50%;
position: relative;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
margin-top: -10px;
margin-bottom: 0px;
  }

/* Tab Weekend */
.tab {
  overflow: hidden;
  background-color: #e84048;
}

/* Style buttons tab */
.tab button {
  background-color: inherit;
  color: white;
  float: left;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 14px 16px;
  transition: 0.3s;
  font-size: 18px;
  font-family:'Roboto Condensed', sans-serif;
}

/* tab buttons hover */
.tab button:hover {
  background-color: #ff8080;
  color: ##e84048
;
}

/* active tablink class */
.tab button.active {
  background-color: #1e0f55;
  color: #e84048
  ;
}

/* Style tab content */
.tabcontent {
  display: none;
  border: none;
}

/* Slideshow container */

* {
    box-sizing: border-box;
}

.mySlides {
    display: none;
}

img {
      vertical-align: middle;
      height:100%;
   }

/* Number text (1/3 etc) */
.numbertext {
    color: #f2f2f2;
    font-size: 12px;
    padding: 8px 12px;
    position: absolute;
    top: 0;
}

   .slideshow-container {
      width: 100vw;
      height: 80vh;
      position: relative;
   }

.overlay {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  opacity: 0;
  transition: .5s ease-in-out;
  background-color: #1e0f55;
  vertical-align: middle;
  width: 100%;
  height:100%;
}

.slideshow-container:hover .overlay {
  opacity: 0.9;
}

/* dots */
.dot {
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

.active {
  background-color: #717171;
}

/* Fading animation Autorun */
.fade {
    -webkit-animation-name: fade;
    -webkit-animation-duration: 2s;
    animation-name: fade;
    animation-duration: 2s;
}

@-webkit-keyframes fade {
    from {
        opacity: .4
    }

    to {
        opacity: 1
    }
}

@keyframes fade {
    from {
        opacity: .4
    }

    to {
        opacity: 1
    }
}

Weekend 1

 27.01 - 29.01

  <button class="tablinks" onclick="mySlides(event, 'firstfriday')">Friday</button>
  <button class="tablinks" onclick="mySlides(event, 'firstsaturday')">Saturday</button>
  <button class="tablinks" onclick="mySlides(event, 'firstsunday')">Sunday</button>

>

1 / 3

RETURN TO THE BEGINNING

15:00 -18:00

Theater

Von 15:00 bis 18:00 Uhr

RETURN TO THE BEGINNING
open rehearsal

Although the work is still in progress, with a premiere scheduled for the end of spring 2023, we have decided to share our work in progress, thanking you in advance for your reflections on the subject.
Three survivors in a cave, inside an old mine, amuse themselves resurrecting possible lives of angels and demons, gods and goddesses in search of a lost truth. None of them lived be-fore the disaster. Who is the son or sister of whom? They don’t even know. They don’t dare to leave the cave or maybe they do...?

Residui Teatro and CAAE

2 / 3

Mehr Impulse

22:00 - 23:00

Music

22:00 - 23:00

Mehr Impulse
Alle Infos - bald hier!

Mehr Impulse

3 / 3

Alle Infos - bald hier!

Uhrzeit

Art der Veranstaltung

...

Alle Infos - bald hier!

...

Friday 27.01.23

1 / 3

THE DANCING ACTOR

10:00 -13:00

Oeffentliche Workshop

Von 10:00 bis 13:00 Uhr

THE DANCING ACTOR

klassischem indischen Tanztheater im Bharata Natyam Stil.Die Teilnehmer werden durch das Ueben und Studieren der Grundelemente des Tanzes, von den Grundschritten bis zu den ersten Prinzipien des Schauspiels, in den Tanz eingefuehrt.
Der Workshop hat einen Umfang von 10h und findet auf Englisch, sowie wenn
nötig mit Übersetzung statt.

mit Caterina Scotti
von Teatro Tascabile di Bergamo

2 / 3

THE DANCING ACTOR

15:00 - 18:00

Oeffentliche Workshop

Von 15:00 bis 18:00 Uhr

THE DANCING ACTOR

klassischem indischen Tanztheater im Bharata Natyam Stil.Die Teilnehmer werden durch das Ueben und Studieren der Grundelemente des Tanzes, von den Grundschritten bis zu den ersten Prinzipien des Schauspiels, in den Tanz eingefuehrt.
Der Workshop hat einen Umfang von 10h und findet auf Englisch, sowie wenn
nötig mit Übersetzung statt.

mit Caterina Scotti
von Teatro Tascabile di Bergamo

3 / 3

Green Clouds
Vapour

22:30 - 23:00

Music

Von 22:30 bis 23:00 Uhr

Vapour is an electro acoustic live performance. A viridescent entity dissolving into heavy storms, gently raining down onto the virtual stage. By creating a fog of synthetic sound objects, we enter the world of a wondrous dormant terrain. Sonic material is composed of mineral vibration and reverberating particles
to form low - pitched holograms, placed in an artificial space. Scanning the green void,
palpating moist textures, observing ambiguous matter, leads to confusing diffusing fading decay. Exhaling misty thoughts, spreading a languid feeling of inertia.

Green Clouds
(David Synth)

Saturday 28.01.23

1 / 3

Beconscious

14:00

Oeffentliche Workshop

Um 14:00 Uhr

Beconscious

In diesem Workshop werden wir mit unseren Körpern und der Beziehung zwischen ihnen spielen, während wir den Prozess in Stille und mit Wohlwollen mental beobachten. Dies geschieht insbesondere durch Techniken des Theaters der Forschung, einem von der Gruppe eingeführten theatralischen Weg. Ziel ist es, als Einheit, aber auch als Ganzes, offener und bewusster an unseren Handlungsort zurückzukehren.
Der Workshop hat einen Umfang von 4h und findet auf Englisch, sowie wenn nötig mit Übersetzung statt.

mit der Multiactive Group
der Art Fabrica Athen

2 / 3

THE DANCING ACTOR

15:00 -18:00

Oeffentliche Workshop

Von 15:00 bis 18:00 Uhr

THE DANCING ACTOR

klassischem indischen Tanztheater im Bharata Natyam Stil.Die Teilnehmer werden durch das Ueben und Studieren der Grundelemente des Tanzes, von den Grundschritten bis zu den ersten Prinzipien des Schauspiels, in den Tanz eingefuehrt.
Der Workshop hat einen Umfang von 10h und findet auf Englisch, sowie wenn
nötig mit Übersetzung statt.

mit Caterina Scotti
von Teatro Tascabile di Bergamo

3 / 3

Meg Ella

22:00 -23:00

Music

Von 22:00 bis 23:00 Uhr

Join us for an intimate concert of original songs from Welsh singer songwriter and multi-instrumentalist Meg Ella. With soaring vocals, intricate harmony and cinematic arrangements she will be joined on stage by world class instrumentalists Fraser Bowles (cello) and Nic Jones (trombone).

Marc Almond and Othon Matargas Now based in London, UK, Meg Ella also works as a vocalist, cellist & pianist as a session musician,  arranger and Musical Director for artists, theatre, film and ensembles.

Meg Ella

Sunday 29.01.23


问:
EOL while scanning SyntaxError for document word count code
I've been handed some code by my lecturer which is to work out the word count for my document (markdown only), when I used it, it worked out the digit count not the word count. I believe the problem is located in the penultimate line .split(), the code initially had '' in the brackets, which I removed to make use of the default (split by whitespaces) but I get an error.
Any help greatly appreciated, novice coder problems.</p>
```<code>import io
from nbformat import read
filepath='DSRM Report 2.ipynb'
with io.open(filepath, 'r', encoding='utf-8') as f:
    nb=read(f, 4)
word_count = 0
for cell in nb\['cells'\]:
    if cell.cell_type == 'markdown':
        word_count += len(cell\['source'\].replace('#',').lstrip().split())
print("Submission length is {}".format(word_count))
</code>```

Body:
I've been handed some code by my lecturer which is to work out the word count for my document (markdown only), when I used it, it worked out the digit count not the word count. I believe the problem is located in the penultimate line .split(), the code initially had '' in the brackets, which I removed to make use of the default (split by whitespaces) but I get an error.
Any help greatly appreciated, novice coder problems.

import io
from nbformat import read
filepath='DSRM Report 2.ipynb'
with io.open(filepath, 'r', encoding='utf-8') as f:
    nb=read(f, 4)
word_count = 0
for cell in nb\['cells'\]:
    if cell.cell_type == 'markdown':
        word_count += len(cell\['source'\].replace('#',').lstrip().split())
print("Submission length is {}".format(word_count))


问:
how EXT4 buffer_head been flushed into disk in buffered IO
Now I have a general question: as we know that-- inode info will be saved in struct buffer_head *bh (in struct ext4_iloc) and then bh will be flushed into disk. So which routine does this flush? I googled and found a link: How Linux struct buffer_head gets flushed? , it mentions "bio structure which is tracked", but I am not fully understand this part. Since I am running fio with buffered IO writing,  not sure it related to pdflush thread? does vfs_cache_pressure controls it?

I read the inode info directly from disk to see the Xtime been updated or not in different scenarios. I found: the Xtime will be updated to disk even "no fsync" or "only fdatasync".
for fdatasync, it will skip update the inode info into disk, how could be the inode info been updated into disk?


问:
Does laravel 9 accepts putting models inside a subfolder ? Like App\Models\Users\User.php
Right after a new laravel 9 installation, ran the code php artisan make:model Users/User -m (and some others in the same path).

Also created a controller AuthController, with 2 methods (register and login)

Register works fine, saves to DB correctly with no problem (using POSTMAN)

But when I try to login, this error appears >

```<code>{
    "message": "Class \"\\App\\Models\\User\" not found",
    "exception": "Error",
    "file": "D:\\sdk\\UniServerZ\\www\\ipas\\vendor\\laravel\\framework\\src\\Illuminate\\Auth\\EloquentUserProvider.php",
    "line": 183,
</code>```

As error says, it's looking for App\Models\User file, which not exist, because when I created the model y said that I wanted to be inside USERS folder ( App\Models\Users\User ) is the correct path.

So, anyone know how can i achieve this ? all my models files were put inside a subfolder, not in Models folder directly D:

Also... I've used namespaces >
in AuthController use App\Models\Users\User;

in User model> namespace App\Models\Users;

Hope you guys understand what I mean, because of my bad english :S

btw, I'm using Sanctum...

I've traced the code, and realized the exception occurs inside login method, in Auth::attempt line > (I've done a print_r, and works)

```<code>    public function login(Request $request){
        if( !Auth::attempt($request->only('email','password')) ){
            return response()
            ->json(['message' => 'Unauthorized']);
        }

        $user   = User::where('email', $request['email'])->firstOrFail();

        $token  = $user->createToken('auth_token')->plainTextToken;

        return response()->json([
            'user'          => $user->name,
            'token'         => $token,
            'token_type'    => 'Bearer',
            'user'          => $user
        ]);
    }
</code>```

Body:
Right after a new laravel 9 installation, ran the code php artisan make:model Users/User -m (and some others in the same path).

Also created a controller AuthController, with 2 methods (register and login)

Register works fine, saves to DB correctly with no problem (using POSTMAN)

But when I try to login, this error appears >

{
    "message": "Class \"\\App\\Models\\User\" not found",
    "exception": "Error",
    "file": "D:\\sdk\\UniServerZ\\www\\ipas\\vendor\\laravel\\framework\\src\\Illuminate\\Auth\\EloquentUserProvider.php",
    "line": 183,

As error says, it's looking for App\Models\User file, which not exist, because when I created the model y said that I wanted to be inside USERS folder ( App\Models\Users\User ) is the correct path.

So, anyone know how can i achieve this ? all my models files were put inside a subfolder, not in Models folder directly D:

Also... I've used namespaces >
in AuthController use App\Models\Users\User;

in User model> namespace App\Models\Users;

Hope you guys understand what I mean, because of my bad english :S

btw, I'm using Sanctum...

I've traced the code, and realized the exception occurs inside login method, in Auth::attempt line > (I've done a print_r, and works)

    public function login(Request $request){
        if( !Auth::attempt($request->only('email','password')) ){
            return response()
            ->json(['message' => 'Unauthorized']);
        }

        $user   = User::where('email', $request['email'])->firstOrFail();

        $token  = $user->createToken('auth_token')->plainTextToken;

        return response()->json([
            'user'          => $user->name,
            'token'         => $token,
            'token_type'    => 'Bearer',
            'user'          => $user
        ]);
    }


问:
Is there a way to clear the query cache?
I notice that even when I remove users from a user group - the rule chain will continue to execute actions using data that should not technically be availible to it.  I can only guess there is a system caching in the database that causes this behavior.

I am wondering how to debug something like that and if there is a way to refresh or clear the caches (if that is in use) to be sure all data is accurate?

I removed users from a User entity Group that was being queried in a rule chain node 'Transformation - duplicate to group by group name'.  Once the rule chain was triggered again, it continued to use old data.


问:
How does Safari handle third-party cookies versus other browsers?
On my job, we serve the oldest version of our product through an iFrame on our partners site (can't give details due to NDA). Recently we found out our app doesn't load on Safari desktop since "Prevent cross-site tracking" in on by default, if you disable that option it works correctly. We know it's because it's treating the session cookie as a third party cookie (remember, iframe through other site) and blocking it.

However, and what I find funny/interesting, is that if I block third party cookies on any other browser (I've tried Chrome, Firefox, Opera, Edge, Samsung and Brave) the site works correctly. It's only Safari where it's breaking, what's even weirder is that on Safari on iOS it doesn't break either, it's just desktop Safari and Safari Technology Preview.
At first I thought that maybe it works on Firefox because it isolates cookies while Safari outright blocks them, but after seeing all the other browsers my best guess is that maybe Safari treats subdomains as third-party while all the other browsers don't.

Unfortunately I can't find any documentation that explains how any of this browsers actually handles blocking third-party cookies / preventing cross-site tracking, only guides on how to toggle it or why it's important.
I'll appreciate any guidance on where I could investigate this or confirm my hipothesis if possible since right now it's more of a burning curiosity thing and less about completing my job.

Thanks a lot have a nice day.


问:
Analysis Table that will be arranged in Deciles to show the value of Absolute Maximum change for Every Trade
INTENTION BEHIND THIS CODE

The intention to build this analysis is to figure out the absolute maximum movement (drawdown or runup) after a signal has been generated. Once the absolute maximum movement is figured out for every trade, the values can be arranged in percentiles, deciles, or quartiles as desired. The absolute maximum movement for the deciles will provide a visual representation of the movement in the underlying after every signal. This will help quickly understand the strength and accuracy of the signal.

I have been working on this for weeks (I am a novice coder) and came up with the script below. I believe
I am close to my desired output. I checked that the values are being generated in the table as desired but
I have done something wrong somewhere in the code and hence the output in the table is haywire (more than required values are appearing and I can only see one column rather than 3 as in my example, because every column has numerous values).

Hoping someone can solve the last piece of puzzle and help me out. Also, they can post the script on TV
as a library for future pine coders.

Find below my code -

```<code>//@version=5
strategy("TestOpen", process_orders_on_close=true, overlay = true)

//DEMO strategy
source = input(title = "Source", defval = close)
smallMAPeriod = input(title = "Small Moving Average", defval = 2)
bigMAPeriod = input(title = "Big Moving Average", defval = 8)
percentBelowToBuy = input(title = "Percent below to buy %", defval = 1)

smallMA = ta.sma(source, smallMAPeriod)
bigMA =  ta.sma(source, bigMAPeriod)
buyMA = ((100 - percentBelowToBuy) / 100) * ta.sma(source, bigMAPeriod)[0]

buy = ta.crossunder(smallMA, buyMA)
if(buy)
    strategy.entry("BUY", strategy.long)

if(strategy.openprofit >= strategy.position_avg_price * 0.01) // 1% profit target
    strategy.close("BUY")

if(ta.barssince(buy) >= 7) //Timed Exit, if you fail to make 1 percent in 7 candles.
    strategy.close("BUY")

//// START OF CODE FOR ANALYZING THE MAX VALUES AND BUILDING THE TABLE \\\\

maxMove() =>

    // create a new array to store the absolute maximum between the drawdown & the runup percent of each trade
    // also create arrays to store the value for the various percentiles/deciles (only 3 shown as example)
    maxArr = array.new_float()
    tenArr = array.new_float() // for ten percentile
    fiftyArr = array.new_float() // for fifty percentile
    ninetyArr = array.new_float() // for ninety percentile

    for i = 0 to strategy.closedtrades -1

        // calculate the absolute drawdown percentage
        drawdown = strategy.closedtrades.max_drawdown(i)
        costBasis = strategy.closedtrades.entry_price(i)
        drawdownPerc = math.abs(drawdown / (costBasis * strategy.closedtrades.size(i)))*100

        // calculate the absolute runup percentage
        runup = strategy.closedtrades.max_runup(i)
        runupPerc = math.abs(runup / (costBasis * strategy.closedtrades.size(i)))*100

        // calculate the max between the absolute drawdown & runup percentage
        max = math.max(drawdownPerc,runupPerc)

        // assign the absolute max values to the array
        array.push(maxArr, max)

       // calculate the values for various percentiles & assign to arrays (only 3 shown as example)
        tenPercent = array.percentile_nearest_rank(maxArr,10) // returns the value at 10th percentile from the maxArr
        array.push(tenArr,tenPercent)
        fiftyPercent = array.percentile_nearest_rank(maxArr,50) // returns the value at 50th percentile from the maxArr
        array.push(fiftyArr,fiftyPercent)
        ninetyPercent = array.percentile_nearest_rank(maxArr,90) // returns the value at 90th percentile from the maxArr
        array.push(ninetyArr,ninetyPercent)

    // created a tuple for the different percentile arrays
    [(tenArr),(fiftyArr),(ninetyArr)]

// table
t = table.new(position = position.bottom_right, columns = 3, rows = 2, bgcolor = color.yellow, frame_color = color.black, border_width = 1, frame_width = 2, border_color = color.black)

if barstate.islastconfirmedhistory
    [tenArr, fiftyArr, ninetyArr] = maxMove()

    // create the cells of the table
    table.cell(table_id = t, column = 0, row = 0, text = "10%")
    table.cell(table_id = t, column = 1, row = 0, text = "50%")
    table.cell(table_id = t, column = 2, row = 0, text = "90")
    table.cell(table_id = t, column = 0, row = 1, text = str.tostring(tenArr, format.percent))
    table.cell(table_id = t, column = 1, row = 1, text = str.tostring(fiftyArr, format.percent))
    table.cell(table_id = t, column = 2, row = 1, text = str.tostring(ninetyArr, format.percent))
</code>```

Body:
INTENTION BEHIND THIS CODE

The intention to build this analysis is to figure out the absolute maximum movement (drawdown or runup) after a signal has been generated. Once the absolute maximum movement is figured out for every trade, the values can be arranged in percentiles, deciles, or quartiles as desired. The absolute maximum movement for the deciles will provide a visual representation of the movement in the underlying after every signal. This will help quickly understand the strength and accuracy of the signal.

I have been working on this for weeks (I am a novice coder) and came up with the script below. I believe
I am close to my desired output. I checked that the values are being generated in the table as desired but
I have done something wrong somewhere in the code and hence the output in the table is haywire (more than required values are appearing and I can only see one column rather than 3 as in my example, because every column has numerous values).

Hoping someone can solve the last piece of puzzle and help me out. Also, they can post the script on TV
as a library for future pine coders.

Find below my code -

//@version=5
strategy("TestOpen", process_orders_on_close=true, overlay = true)

//DEMO strategy
source = input(title = "Source", defval = close)
smallMAPeriod = input(title = "Small Moving Average", defval = 2)
bigMAPeriod = input(title = "Big Moving Average", defval = 8)
percentBelowToBuy = input(title = "Percent below to buy %", defval = 1)

smallMA = ta.sma(source, smallMAPeriod)
bigMA =  ta.sma(source, bigMAPeriod)
buyMA = ((100 - percentBelowToBuy) / 100) * ta.sma(source, bigMAPeriod)[0]

buy = ta.crossunder(smallMA, buyMA)
if(buy)
    strategy.entry("BUY", strategy.long)

if(strategy.openprofit >= strategy.position_avg_price * 0.01) // 1% profit target
    strategy.close("BUY")

if(ta.barssince(buy) >= 7) //Timed Exit, if you fail to make 1 percent in 7 candles.
    strategy.close("BUY")

//// START OF CODE FOR ANALYZING THE MAX VALUES AND BUILDING THE TABLE \\\\

maxMove() =>

    // create a new array to store the absolute maximum between the drawdown & the runup percent of each trade
    // also create arrays to store the value for the various percentiles/deciles (only 3 shown as example)
    maxArr = array.new_float()
    tenArr = array.new_float() // for ten percentile
    fiftyArr = array.new_float() // for fifty percentile
    ninetyArr = array.new_float() // for ninety percentile

    for i = 0 to strategy.closedtrades -1

        // calculate the absolute drawdown percentage
        drawdown = strategy.closedtrades.max_drawdown(i)
        costBasis = strategy.closedtrades.entry_price(i)
        drawdownPerc = math.abs(drawdown / (costBasis * strategy.closedtrades.size(i)))*100

        // calculate the absolute runup percentage
        runup = strategy.closedtrades.max_runup(i)
        runupPerc = math.abs(runup / (costBasis * strategy.closedtrades.size(i)))*100

        // calculate the max between the absolute drawdown & runup percentage
        max = math.max(drawdownPerc,runupPerc)

        // assign the absolute max values to the array
        array.push(maxArr, max)

       // calculate the values for various percentiles & assign to arrays (only 3 shown as example)
        tenPercent = array.percentile_nearest_rank(maxArr,10) // returns the value at 10th percentile from the maxArr
        array.push(tenArr,tenPercent)
        fiftyPercent = array.percentile_nearest_rank(maxArr,50) // returns the value at 50th percentile from the maxArr
        array.push(fiftyArr,fiftyPercent)
        ninetyPercent = array.percentile_nearest_rank(maxArr,90) // returns the value at 90th percentile from the maxArr
        array.push(ninetyArr,ninetyPercent)

    // created a tuple for the different percentile arrays
    [(tenArr),(fiftyArr),(ninetyArr)]

// table
t = table.new(position = position.bottom_right, columns = 3, rows = 2, bgcolor = color.yellow, frame_color = color.black, border_width = 1, frame_width = 2, border_color = color.black)

if barstate.islastconfirmedhistory
    [tenArr, fiftyArr, ninetyArr] = maxMove()

    // create the cells of the table
    table.cell(table_id = t, column = 0, row = 0, text = "10%")
    table.cell(table_id = t, column = 1, row = 0, text = "50%")
    table.cell(table_id = t, column = 2, row = 0, text = "90")
    table.cell(table_id = t, column = 0, row = 1, text = str.tostring(tenArr, format.percent))
    table.cell(table_id = t, column = 1, row = 1, text = str.tostring(fiftyArr, format.percent))
    table.cell(table_id = t, column = 2, row = 1, text = str.tostring(ninetyArr, format.percent))


问:
When closing Kivy app settings, UI text changes don't work
When I start the following app and click btn2 I observe the text of the button change as I would expect. When I open settings using btn1, then close settings and then click btn2 the text does not change again, yet the button is pressed (message is printed). I have noticed this happening with other labels as well and I don't understand why. It should be noted that the callback is called as expected and the message printed with the same button instance.

While debugging this I also found that the counter keeps incrementing as expected but the text becomes an empty string after the settings are closed and updating it does not reflect onto the app UI.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

class MainLayout(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        btn1 = Button(text="Settings", size_hint=(.5, 1), on_press=self.btn1_on_press)
        btn2 = Button(text="0", size_hint=(.5, 1), on_press=self.btn2_on_press)
        self.add_widget(btn1)
        self.add_widget(btn2)
        self.counter = 0

    def btn1_on_press(self, btn):
        app.open_settings()

    def btn2_on_press(self, btn):
        print("btn pressed: ", btn)
        self.counter += 1
        btn.text = str(self.counter)

class MyApp(App):
    def build(self):
        self.use_kivy_settings = False
        return MainLayout()

    def build_config(self, config):
        config.setdefaults("settings", {
            "dark_mode": True,
        })

    def build_settings(self, settings):
        settings.add_json_panel("settings", self.config, data="""[
            {
                "type": "bool",
                "title": "Dark mode",
                "desc": "Enable dark mode",
                "section": "settings",
                "key": "dark_mode"
            }
        ]""")

if __name__ == '__main__':
    app = MyApp()
    app.run()
```
<p>The current kivy version I use is 2.1.0.</p>
```$ pip freeze | grep -i kivy
Kivy==2.1.0
Kivy-Garden==0.1.5
```

Body:
When I start the following app and click btn2 I observe the text of the button change as I would expect. When I open settings using btn1, then close settings and then click btn2 the text does not change again, yet the button is pressed (message is printed). I have noticed this happening with other labels as well and I don't understand why. It should be noted that the callback is called as expected and the message printed with the same button instance.

While debugging this I also found that the counter keeps incrementing as expected but the text becomes an empty string after the settings are closed and updating it does not reflect onto the app UI.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

class MainLayout(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        btn1 = Button(text="Settings", size_hint=(.5, 1), on_press=self.btn1_on_press)
        btn2 = Button(text="0", size_hint=(.5, 1), on_press=self.btn2_on_press)
        self.add_widget(btn1)
        self.add_widget(btn2)
        self.counter = 0

    def btn1_on_press(self, btn):
        app.open_settings()

    def btn2_on_press(self, btn):
        print("btn pressed: ", btn)
        self.counter += 1
        btn.text = str(self.counter)

class MyApp(App):
    def build(self):
        self.use_kivy_settings = False
        return MainLayout()

    def build_config(self, config):
        config.setdefaults("settings", {
            "dark_mode": True,
        })

    def build_settings(self, settings):
        settings.add_json_panel("settings", self.config, data="""[
            {
                "type": "bool",
                "title": "Dark mode",
                "desc": "Enable dark mode",
                "section": "settings",
                "key": "dark_mode"
            }
        ]""")

if __name__ == '__main__':
    app = MyApp()
    app.run()

The current kivy version I use is 2.1.0.

$ pip freeze | grep -i kivy
Kivy==2.1.0
Kivy-Garden==0.1.5


问:
Angular 15 with Jest Preset Angular reports: Component ... is not resolved... Did you run and wait for 'resolveComponentResources()'?
Jest used to work with angular for me (on ng11, 7 months ago). Then I accidentally rebuilt my package-lock and some updated dependency somewhere broke things so I tabled it.

The other day, I updated to ng15, and tests are running but are all failing with Did you run and wait for 'resolveComponentResources()'? edit: not all tests are failing with that error; just those that rely on TestBed.createComponent or TestBed.inject

I've seen a lot of bug reports mentioning this kind of problem, stretching back to ng8, so I assume it's just some kind of incompatibility or bad conf. The most recent I found reported success by downgrading typescript to 4.7 but that's not possible with ng15.

The project is node+angular together in separate folders (the root package.json controls the server and the jest runner). Relevant snippets below:

package.json

```<code>{
  ...
  "engineStrict": true,
  "engines": {
    "node": "18.12.1"
  },
  "scripts": {
    ...
    "test": "./test-data/test-data.sh && jest --detectOpenHandles",
    "test:watch": "./test-data/test-data.sh && jest --detectOpenHandles --watch"
  },
  "jest": {
    "verbose": true,
    "collectCoverage": true,
    "collectCoverageFrom": [
      "**/*.{js,ts}",
      "!**/*.spec.{js,ts}",
      "!**/serviceWorker.js",
      "!**/node_modules/**",
      "!**/data/**",
      "!**/environments/**",
      "!**/migrations/**",
      "!**/server/config/**",
      "!**/vendors/**",
      "!**/coverage/**",
      "!**/models/**",
      "!**/test-data/**",
      "!**/migration.js",
      "!**/app.module.ts",
      "!**/*webpack.config.js",
      "!**/*main.ts",
      "!**/*polyfills.ts"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>/*/node_modules/",
      "<rootDir>/client/dist/"
    ],
    "projects": [
      {
        "displayName": "backend",
        "testEnvironment": "node",
        "testMatch": [
          "<rootDir>/server/**/*.spec.js"
        ],
        "modulePaths": [
          "<rootDir>/server/"
        ]
      },
      {
        "displayName": "frontend",
        "testEnvironment": "jsdom",
        "preset": "<rootDir>/client/node_modules/jest-preset-angular",
        "setupFilesAfterEnv": [
          "<rootDir>/client/setupJest.ts"
        ],
        "testMatch": [
          "<rootDir>/client/src/**/*.spec.ts"
        ],
        "modulePaths": [
          "<rootDir>/client/"
        ],
        "snapshotSerializers": [
          "<rootDir>/client/node_modules/jest-preset-angular/build/serializers/html-comment"
        ],
        "transform": {
          "^.+\\.(ts|js|mjs|html|svg)$": "<rootDir>/client/node_modules/jest-preset-angular"
        },
        "transformIgnorePatterns": ["node_modules/(?!.*\\.mjs$)"],
        "globals": {
          "ts-jest": {
            "tsconfig": "<rootDir>/client/tsconfig.spec.json",
            "stringifyContentPathRegex": "\\.html$"
          }
        },
        "globalSetup": "<rootDir>/client/node_modules/jest-preset-angular/global-setup"
      }
    ]
  },
  ...
  "devDependencies": {
    "ajv-cli": "^5.0.0",
    "db-migrate-mysql": "^1.1.10",
    "jest": "29.3.1",
    "jest-environment-jsdom": "29.3.1",
    "mysql-migrations": "^1.0.6",
    "node-env-run": "^4.0.2",
    "nodemon": "^1.19.4",
    "npm-run-all": "^4.1.5",
    "pino-colada": "^1.6.0",
    "ts-json-schema-generator": "^1.0.0"
  }
}
</code>```

client/package.json:

```<code>{
  ...
  "private": true,
  "dependencies": {
    "@angular-builders/custom-webpack": "^15.0.0",
    "@angular-devkit/build-angular": "^15.0.4",
    "@angular/animations": "^15.0.4",
    "@angular/cli": "^15.0.4",
    "@angular/common": "^15.0.4",
    "@angular/compiler": "^15.0.4",
    "@angular/compiler-cli": "^15.0.4",
    "@angular/core": "^15.0.4",
    "@angular/fire": "^7.5.0",
    "@angular/forms": "^15.0.4",
    "@angular/platform-browser": "^15.0.4",
    "@angular/platform-browser-dynamic": "^15.0.4",
    "@angular/router": "^15.0.4",
    ...
    "tslib": "^2.0.0",
    "typescript": "4.8.3",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-builders/dev-server": "^7.3.1",
    "@angular-devkit/architect": "0.1500.4",
    "@angular-eslint/schematics": "^15.1.0",
    "@types/clone": "^2.1.1",
    "@types/file-saver": "^2.0.5",
    "@types/jest": "^29.2.5",
    "@types/node": "^12.20.7",
    "@types/string-similarity": "^4.0.0",
    ...
    "jest-preset-angular": "^12.2.3",
    "jsonc-parser": "^3.0.0",
    "open": "^7.0.3",
    "rxjs-watcher": "^1.1.3",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0"
  }
}
</code>```

angular.json

```<code>{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "rosterizer": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "sass"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "outputPath": "dist/rosterizer",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/site.webmanifest",
              "src/assets"
            ],
            "styles": [
              "src/css/main.sass"
            ],
            "scripts": [
              "node_modules/marked/marked.min.js"
            ],
            "webWorkerTsConfig": "tsconfig.worker.json",
            "customWebpackConfig": {
              "path": "custom-webpack.config.ts",
              "replaceDuplicatePlugins": true
            }
          },
          "configurations": {
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true
            },
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "3mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "browserTarget": "myApp:build",
            "proxyConfig": "src/proxy.conf.json"
          },
          "configurations": {
            "development": {
              "browserTarget": "myApp:build:development"
            },
            "production": {
              "browserTarget": "myApp:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "myApp:build"
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "myApp:serve"
          },
          "configurations": {
            "development": {
              "devServerTarget": "myApp:serve:development"
            },
            "production": {
              "devServerTarget": "myApp:serve:production"
            }
          }
        },
        "deploy": {
          "builder": "@angular/fire:deploy",
          "options": {}
        }
      }
    }
  }
}
</code>```

custom-webpack.config.ts

```<code>const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
    // Other rules...
    plugins: [
        new NodePolyfillPlugin()
    ]
};
</code>```

tsconfig.json

```<code>{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "ES2022",
    "module": "es2020",
    "lib": [
      "es2020",
      "dom",
      "ESNext.String"
    ],
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "useDefineForClassFields": false
  },
  "emitDecoratorMetadata":true
}
</code>```

tsconfig.spec.json

```<code>const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
    // Other rules...
    plugins: [
        new NodePolyfillPlugin()
    ]
};
</code>```

Body:
Jest used to work with angular for me (on ng11, 7 months ago). Then I accidentally rebuilt my package-lock and some updated dependency somewhere broke things so I tabled it.

The other day, I updated to ng15, and tests are running but are all failing with Did you run and wait for 'resolveComponentResources()'? edit: not all tests are failing with that error; just those that rely on TestBed.createComponent or TestBed.inject

I've seen a lot of bug reports mentioning this kind of problem, stretching back to ng8, so I assume it's just some kind of incompatibility or bad conf. The most recent I found reported success by downgrading typescript to 4.7 but that's not possible with ng15.

The project is node+angular together in separate folders (the root package.json controls the server and the jest runner). Relevant snippets below:

package.json

{
  ...
  "engineStrict": true,
  "engines": {
    "node": "18.12.1"
  },
  "scripts": {
    ...
    "test": "./test-data/test-data.sh && jest --detectOpenHandles",
    "test:watch": "./test-data/test-data.sh && jest --detectOpenHandles --watch"
  },
  "jest": {
    "verbose": true,
    "collectCoverage": true,
    "collectCoverageFrom": [
      "**/*.{js,ts}",
      "!**/*.spec.{js,ts}",
      "!**/serviceWorker.js",
      "!**/node_modules/**",
      "!**/data/**",
      "!**/environments/**",
      "!**/migrations/**",
      "!**/server/config/**",
      "!**/vendors/**",
      "!**/coverage/**",
      "!**/models/**",
      "!**/test-data/**",
      "!**/migration.js",
      "!**/app.module.ts",
      "!**/*webpack.config.js",
      "!**/*main.ts",
      "!**/*polyfills.ts"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>/*/node_modules/",
      "<rootDir>/client/dist/"
    ],
    "projects": [
      {
        "displayName": "backend",
        "testEnvironment": "node",
        "testMatch": [
          "<rootDir>/server/**/*.spec.js"
        ],
        "modulePaths": [
          "<rootDir>/server/"
        ]
      },
      {
        "displayName": "frontend",
        "testEnvironment": "jsdom",
        "preset": "<rootDir>/client/node_modules/jest-preset-angular",
        "setupFilesAfterEnv": [
          "<rootDir>/client/setupJest.ts"
        ],
        "testMatch": [
          "<rootDir>/client/src/**/*.spec.ts"
        ],
        "modulePaths": [
          "<rootDir>/client/"
        ],
        "snapshotSerializers": [
          "<rootDir>/client/node_modules/jest-preset-angular/build/serializers/html-comment"
        ],
        "transform": {
          "^.+\\.(ts|js|mjs|html|svg)$": "<rootDir>/client/node_modules/jest-preset-angular"
        },
        "transformIgnorePatterns": ["node_modules/(?!.*\\.mjs$)"],
        "globals": {
          "ts-jest": {
            "tsconfig": "<rootDir>/client/tsconfig.spec.json",
            "stringifyContentPathRegex": "\\.html$"
          }
        },
        "globalSetup": "<rootDir>/client/node_modules/jest-preset-angular/global-setup"
      }
    ]
  },
  ...
  "devDependencies": {
    "ajv-cli": "^5.0.0",
    "db-migrate-mysql": "^1.1.10",
    "jest": "29.3.1",
    "jest-environment-jsdom": "29.3.1",
    "mysql-migrations": "^1.0.6",
    "node-env-run": "^4.0.2",
    "nodemon": "^1.19.4",
    "npm-run-all": "^4.1.5",
    "pino-colada": "^1.6.0",
    "ts-json-schema-generator": "^1.0.0"
  }
}

client/package.json:

{
  ...
  "private": true,
  "dependencies": {
    "@angular-builders/custom-webpack": "^15.0.0",
    "@angular-devkit/build-angular": "^15.0.4",
    "@angular/animations": "^15.0.4",
    "@angular/cli": "^15.0.4",
    "@angular/common": "^15.0.4",
    "@angular/compiler": "^15.0.4",
    "@angular/compiler-cli": "^15.0.4",
    "@angular/core": "^15.0.4",
    "@angular/fire": "^7.5.0",
    "@angular/forms": "^15.0.4",
    "@angular/platform-browser": "^15.0.4",
    "@angular/platform-browser-dynamic": "^15.0.4",
    "@angular/router": "^15.0.4",
    ...
    "tslib": "^2.0.0",
    "typescript": "4.8.3",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-builders/dev-server": "^7.3.1",
    "@angular-devkit/architect": "0.1500.4",
    "@angular-eslint/schematics": "^15.1.0",
    "@types/clone": "^2.1.1",
    "@types/file-saver": "^2.0.5",
    "@types/jest": "^29.2.5",
    "@types/node": "^12.20.7",
    "@types/string-similarity": "^4.0.0",
    ...
    "jest-preset-angular": "^12.2.3",
    "jsonc-parser": "^3.0.0",
    "open": "^7.0.3",
    "rxjs-watcher": "^1.1.3",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0"
  }
}

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "rosterizer": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "sass"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "outputPath": "dist/rosterizer",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/site.webmanifest",
              "src/assets"
            ],
            "styles": [
              "src/css/main.sass"
            ],
            "scripts": [
              "node_modules/marked/marked.min.js"
            ],
            "webWorkerTsConfig": "tsconfig.worker.json",
            "customWebpackConfig": {
              "path": "custom-webpack.config.ts",
              "replaceDuplicatePlugins": true
            }
          },
          "configurations": {
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true
            },
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "3mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "browserTarget": "myApp:build",
            "proxyConfig": "src/proxy.conf.json"
          },
          "configurations": {
            "development": {
              "browserTarget": "myApp:build:development"
            },
            "production": {
              "browserTarget": "myApp:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "myApp:build"
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "myApp:serve"
          },
          "configurations": {
            "development": {
              "devServerTarget": "myApp:serve:development"
            },
            "production": {
              "devServerTarget": "myApp:serve:production"
            }
          }
        },
        "deploy": {
          "builder": "@angular/fire:deploy",
          "options": {}
        }
      }
    }
  }
}

custom-webpack.config.ts

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
    // Other rules...
    plugins: [
        new NodePolyfillPlugin()
    ]
};

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "ES2022",
    "module": "es2020",
    "lib": [
      "es2020",
      "dom",
      "ESNext.String"
    ],
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "useDefineForClassFields": false
  },
  "emitDecoratorMetadata":true
}

tsconfig.spec.json

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
    // Other rules...
    plugins: [
        new NodePolyfillPlugin()
    ]
};


问:
Place ID showing "NOT FOUND" error for place details API - outdated place ID
Trying to use Places API but the place ID is not valid. I have tried to use the nearby search but I keep coming up with Not Found error or invalid ID.

It is a service area business so I got the ID from inspecting the Write a Review for the GB profile.

This is the nearby search string I'm using (with exact lat/long) but it's not returning the searched business (it does return nearby businesses). Found this from Place ID gives "NOT FOUND" error for place details API:

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.944640,151.228100&key=API-KEY&rankby=distance&pagetoken=

A place ID is showing on Google but when I try to use it with my API, it says it needs to be refreshed in the cache.

I've tried the Google maps nearby search but I'm either not getting the URL string correct or it's just not working.

Name of company is: Key Solutions Locksmith (current - invalid - place ID: ChIJ4ZphJoX7c6kRcsTRFd-cd_Y)

This is the nearby search string I'm using (with exact lat/long) but it's not returning the searched business (it does return nearby businesses but they all seem to be storefront instead of service area.

Also tried: https://maps.googleapis.com/maps/api/place/autocomplete/json?input=NUMBER%20STREETNAME%20Street,%20Maroubra,%202035&types=address&components=country:au&key=API-KEY

with just the address but the place ID it returned shows no reviews so it's not connected to the actual service area business.

How can I get a new (refresh) my place ID to get it to work with the Places API?

Thanks


问:
How do i Edit records in a .txt file in Java?
I'm using NetBeans 16 and I'm trying to add the ability to edit a record from a text file I have saved separated by commas.

Ive tried this code here and I don't seem to get any errors (except the one produced as a result of the try catch) but I have no idea why this doesn't seem to work when I try to overwrite a record which I have selected ive tried everything I can think of I'm pretty new to coding so forgive me if there's some obvious error but I have no idea why this doesn't work my text file has 5 entries in a row if that helps but yeah any help is greatly appreciated

```<code>public class EditRecords {

    private static Scanner x;

    public static void main(String[]args)
    {

        String filepath = "VehicleInforUpd.txt";

            System.out.println("Enter Registration of Entry You Wish To Edit");
            Scanner scanner = new Scanner(System.in);
            String editTerm = scanner.nextLine();

            System.out.println("Enter new Registration: ");
            String newReg = scanner.nextLine();

            System.out.println("Enter new Make: ");
            String newMake = scanner.nextLine();

            System.out.println("Enter New Model: ");
            String newModel = scanner.nextLine();

            System.out.println("Enter New Year: ");
            String newYear = scanner.nextLine();

            System.out.println("Enter New Comments: ");
            String newComment = scanner.nextLine();

            editRecord(filepath,editTerm,newReg,newMake,newModel,newYear,newComment);
        }

    public static void editRecord(String filepath,String editTerm,String newReg,String newMake,String newModel, String newYear, String newComment)
    {
        String tempFile = "temp.txt";
        File oldFile = new File(filepath);
        File newFile = new File(tempFile);
        String reg = ""; String make = ""; String model = ""; String year = ""; String comment = "";

        try
        {
            FileWriter fw = new FileWriter(tempFile,true);
            BufferedWriter bw = new BufferedWriter(fw);
            PrintWriter pw = new PrintWriter(bw);

            while(x.hasNext())
            {
                reg = x.next();
                make = x.next();
                model = x.next();
                year = x.next();
                comment = x.next();

                if(reg.equals(editTerm))
                {
                    pw.println(newReg+","+newMake+","+newModel+","+ newYear+","+newComment);
                }
                else
                {
                    pw.println(reg+","+make+","+model+","+year+","+comment);
                }

            }
            x.close();
            pw.flush();
            pw.close();
            oldFile.delete();
            File dump = new File(filepath);
            newFile.renameTo(dump);
            JOptionPane.showMessageDialog(null, "Changes Succesfully Saved");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
</code>```

The Print stack trace results but im not sure what would cause the NullPointerException im getting

```<code>java.lang.NullPointerException
    at com.mycompany.anprsystems.EditRecords.editRecord(EditRecords.java:70)
    at com.mycompany.anprsystems.EditRecords.main(EditRecords.java:52)
</code>```

Body:
I'm using NetBeans 16 and I'm trying to add the ability to edit a record from a text file I have saved separated by commas.

Ive tried this code here and I don't seem to get any errors (except the one produced as a result of the try catch) but I have no idea why this doesn't seem to work when I try to overwrite a record which I have selected ive tried everything I can think of I'm pretty new to coding so forgive me if there's some obvious error but I have no idea why this doesn't work my text file has 5 entries in a row if that helps but yeah any help is greatly appreciated

public class EditRecords {

    private static Scanner x;

    public static void main(String[]args)
    {

        String filepath = "VehicleInforUpd.txt";

            System.out.println("Enter Registration of Entry You Wish To Edit");
            Scanner scanner = new Scanner(System.in);
            String editTerm = scanner.nextLine();

            System.out.println("Enter new Registration: ");
            String newReg = scanner.nextLine();

            System.out.println("Enter new Make: ");
            String newMake = scanner.nextLine();

            System.out.println("Enter New Model: ");
            String newModel = scanner.nextLine();

            System.out.println("Enter New Year: ");
            String newYear = scanner.nextLine();

            System.out.println("Enter New Comments: ");
            String newComment = scanner.nextLine();

            editRecord(filepath,editTerm,newReg,newMake,newModel,newYear,newComment);
        }

    public static void editRecord(String filepath,String editTerm,String newReg,String newMake,String newModel, String newYear, String newComment)
    {
        String tempFile = "temp.txt";
        File oldFile = new File(filepath);
        File newFile = new File(tempFile);
        String reg = ""; String make = ""; String model = ""; String year = ""; String comment = "";

        try
        {
            FileWriter fw = new FileWriter(tempFile,true);
            BufferedWriter bw = new BufferedWriter(fw);
            PrintWriter pw = new PrintWriter(bw);

            while(x.hasNext())
            {
                reg = x.next();
                make = x.next();
                model = x.next();
                year = x.next();
                comment = x.next();

                if(reg.equals(editTerm))
                {
                    pw.println(newReg+","+newMake+","+newModel+","+ newYear+","+newComment);
                }
                else
                {
                    pw.println(reg+","+make+","+model+","+year+","+comment);
                }

            }
            x.close();
            pw.flush();
            pw.close();
            oldFile.delete();
            File dump = new File(filepath);
            newFile.renameTo(dump);
            JOptionPane.showMessageDialog(null, "Changes Succesfully Saved");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

The Print stack trace results but im not sure what would cause the NullPointerException im getting

java.lang.NullPointerException
    at com.mycompany.anprsystems.EditRecords.editRecord(EditRecords.java:70)
    at com.mycompany.anprsystems.EditRecords.main(EditRecords.java:52)