问:
Stubbing Google Maps JS API loader in Cypress
I'm using the Google Maps JS API in my app for autocompletion and geocoding. The API is loaded using the Google Maps JS API Loader. As I'm end-to-end testing with Cypress, I'm trying to mock out the API, but I can't figure out how to make it work.

I abstract the API in a separate module. This is how it is loaded and instantiated (the code is reduced to the essentials):

import {Loader} from "@googlemaps/js-api-loader";

// The Google Maps API has to be loaded dynamically.
// We have to do this here as it is loaded asynchronously and otherwise we won't
//  be able to just create the class below.
let loading: Promise<typeof google>;
try {
  loading = new Loader({
    apiKey: "private key",
    libraries: ["places"],
  }).load();
} catch (e) {
  console.error("Failed to load Google Maps API");
}

class GoogleMapsAPI {
  private autocompleteService: google.maps.places.AutocompleteService;
  private readonly sessionToken: google.maps.places.AutocompleteSessionToken;
  private predictions: google.maps.places.AutocompletePrediction[];

  constructor() {
    this.autocompleteService = new google.maps.places.AutocompleteService();

    // As an instance is created every time we use this, we set the session here
    this.sessionToken = new google.maps.places.AutocompleteSessionToken();
    this.predictions = []
  }

  public async getPredictions(input: string): Promise<google.maps.places.AutocompletePrediction[]> {
    // Search for the input string and store the returned results
    try {
      const result = await this.autocompleteService.getPlacePredictions({
        input,
        sessionToken: this.sessionToken
      });

      // Replace the previous predictions
      this.predictions = result.results;
      return this.predictions;
    } catch (e: any) {
      console.error(`Autocomplete call failed: ${e}`);
      return [];
    }
  }
}

async function loadGoogleMapsAPI(): Promise<GoogleMapsAPI | null> {
  // Wait for the loader to load the API, then return the API class.
  try {
    await loading;

    return new GoogleMapsAPI();
  } catch (e) {
    console.error(`Google Maps API could not be loaded`);
  }

  return null;
}
```
<p>This is how I use the API in my React app:</p>
<pre class="lang-js prettyprint-override"><code>import React, {useEffect, useState} from "react";

import {GoogleMapsAPI, loadGoogleMapsAPI} from "../../services/google";

export default function Site() {
  const [api, setAPI] = useState<GoogleMapsAPI | null>(null);

  useEffect(() => {
    loadGoogleMapsAPI()
      .then((api) => {
        setAPI(api);
      })
  });

  return <div>API valid: {api ? "yes" : "no"}</div>;
}
</code>```

And this is how I try to test it:

import {Loader} from "@googlemaps/js-api-loader";

describe("Test", () => {
  it("Google Maps not found", () => {
    cy.visit(
      "/",
      {
        onBeforeLoad(win: Cypress.AUTWindow) {
          // Mock the load method of Loader to prevent it from ever requesting
          //  the Google Maps API script file
          cy.stub(Loader.prototype, "load").resolves(true);

          // Replace the Google Maps API created by the Google Maps API Loader
          //  with our mocks
          win.google = {
            maps: {
              places: {
                AutocompleteSessionToken: class {},
                AutocompleteService: class {
                  async getPlacePredictions(request: any) {
                    return Promise.resolve({ predictions: [] });
                  }
                } as any,
              } as any
            } as any
          };
        }
      }
    );

    cy.get("API valid: yes"); // Fails consistently
  });
});
```

I'm stubbing out the load method of the Loader class and then try to add a mock Google Maps services to the window.

My problem is that neither stubbing the loader doesn't work - according to Cypress the stub is never even called and, of course, the promise doesn't resolve then either.
Another approach I tried was to stub loadGoogleMapsAPI and manually return an instance of GoogleMapsAPI, but the issue remains the same - I never get the predictions returned by google.maps.places.autocompleteService.getPlacePredictions via getPlacePredictions.

As I'm pretty new to testing with Cypress and testing frontend code in general this might just be a misundernstanding of how stubbing in Cypress works or how code is loaded in JS, but I'm pretty much stuck here and would appreciate any help!

答:
I've solved the issue by getting rid of the loader in favor of inline loading and the following code:

let ready = false;

// This is the callback that is called by the Google Maps API loader script
//  loaded in index.html.
window.initGoogleMapsAPI = function() {
  ready = true;
}

async function waitForGoogleMapsAPI(): Promise<void> {
  return new Promise<void>((resolve) => {
    if (ready) {
      resolve();
    }
  })
}

...

async function loadGoogleMapsAPI(): Promise<GoogleMapsAPI | null> {
  // Wait for the loader to load the API, then return the API class.
  try {
    await waitForGoogleMapsAPI;

    return new GoogleMapsAPI();
  } catch (e) {
    console.error(`Google Maps API could not be loaded: ${e}`);
  }

  return null;
}
```

Then I export waitForGoogleMapsAPI and mock it in the test.

Body:
I'm using the Google Maps JS API in my app for autocompletion and geocoding. The API is loaded using the Google Maps JS API Loader. As I'm end-to-end testing with Cypress, I'm trying to mock out the API, but I can't figure out how to make it work.

I abstract the API in a separate module. This is how it is loaded and instantiated (the code is reduced to the essentials):

import {Loader} from "@googlemaps/js-api-loader";

// The Google Maps API has to be loaded dynamically.
// We have to do this here as it is loaded asynchronously and otherwise we won't
//  be able to just create the class below.
let loading: Promise<typeof google>;
try {
  loading = new Loader({
    apiKey: "private key",
    libraries: ["places"],
  }).load();
} catch (e) {
  console.error("Failed to load Google Maps API");
}

class GoogleMapsAPI {
  private autocompleteService: google.maps.places.AutocompleteService;
  private readonly sessionToken: google.maps.places.AutocompleteSessionToken;
  private predictions: google.maps.places.AutocompletePrediction[];

  constructor() {
    this.autocompleteService = new google.maps.places.AutocompleteService();

    // As an instance is created every time we use this, we set the session here
    this.sessionToken = new google.maps.places.AutocompleteSessionToken();
    this.predictions = []
  }

  public async getPredictions(input: string): Promise<google.maps.places.AutocompletePrediction[]> {
    // Search for the input string and store the returned results
    try {
      const result = await this.autocompleteService.getPlacePredictions({
        input,
        sessionToken: this.sessionToken
      });

      // Replace the previous predictions
      this.predictions = result.results;
      return this.predictions;
    } catch (e: any) {
      console.error(`Autocomplete call failed: ${e}`);
      return [];
    }
  }
}

async function loadGoogleMapsAPI(): Promise<GoogleMapsAPI | null> {
  // Wait for the loader to load the API, then return the API class.
  try {
    await loading;

    return new GoogleMapsAPI();
  } catch (e) {
    console.error(`Google Maps API could not be loaded`);
  }

  return null;
}

This is how I use the API in my React app:

import React, {useEffect, useState} from "react";

import {GoogleMapsAPI, loadGoogleMapsAPI} from "../../services/google";

export default function Site() {
  const [api, setAPI] = useState<GoogleMapsAPI | null>(null);

  useEffect(() => {
    loadGoogleMapsAPI()
      .then((api) => {
        setAPI(api);
      })
  });

  return
API valid: {api ? "yes" : "no"}
;
}

And this is how I try to test it:

import {Loader} from "@googlemaps/js-api-loader";

describe("Test", () => {
  it("Google Maps not found", () => {
    cy.visit(
      "/",
      {
        onBeforeLoad(win: Cypress.AUTWindow) {
          // Mock the load method of Loader to prevent it from ever requesting
          //  the Google Maps API script file
          cy.stub(Loader.prototype, "load").resolves(true);

          // Replace the Google Maps API created by the Google Maps API Loader
          //  with our mocks
          win.google = {
            maps: {
              places: {
                AutocompleteSessionToken: class {},
                AutocompleteService: class {
                  async getPlacePredictions(request: any) {
                    return Promise.resolve({ predictions: [] });
                  }
                } as any,
              } as any
            } as any
          };
        }
      }
    );

    cy.get("API valid: yes"); // Fails consistently
  });
});

I'm stubbing out the load method of the Loader class and then try to add a mock Google Maps services to the window.

My problem is that neither stubbing the loader doesn't work - according to Cypress the stub is never even called and, of course, the promise doesn't resolve then either.
Another approach I tried was to stub loadGoogleMapsAPI and manually return an instance of GoogleMapsAPI, but the issue remains the same - I never get the predictions returned by google.maps.places.autocompleteService.getPlacePredictions via getPlacePredictions.

As I'm pretty new to testing with Cypress and testing frontend code in general this might just be a misundernstanding of how stubbing in Cypress works or how code is loaded in JS, but I'm pretty much stuck here and would appreciate any help!

Body:
I've solved the issue by getting rid of the loader in favor of inline loading and the following code:

let ready = false;

// This is the callback that is called by the Google Maps API loader script
//  loaded in index.html.
window.initGoogleMapsAPI = function() {
  ready = true;
}

async function waitForGoogleMapsAPI(): Promise<void> {
  return new Promise<void>((resolve) => {
    if (ready) {
      resolve();
    }
  })
}

...

async function loadGoogleMapsAPI(): Promise<GoogleMapsAPI | null> {
  // Wait for the loader to load the API, then return the API class.
  try {
    await waitForGoogleMapsAPI;

    return new GoogleMapsAPI();
  } catch (e) {
    console.error(`Google Maps API could not be loaded: ${e}`);
  }

  return null;
}

Then I export waitForGoogleMapsAPI and mock it in the test.


来源: stackexchange

问:
Angular|RxJS - Type-ahead search request gets cancelled by browser (on click)
I am new to RxJS (and frontend) but I know that switchMap() in the following code is used to break and re-run a search request as the user types into a text box. Search works fine, the only problem is that if the user clicks anywhere outside the textbox (like anywhere on the page, or on a different browser tab or window, or chrome devtools) after entering the text and before the request is fulfilled, the browser cancels the search request altogether.

(Note: The search request is cancelled and re-run correctly if user keeps typing while the request is being processed. Only click event causes the complete request cancellation without re-run)

  search = (input: Observable<string>) => {
    return input.pipe(
      debounceTime(500),
      distinctUntilChanged(),
      switchMap((text) => text.length < 2 ? this.clearDropDown() // clear dropdown showing list of item names.
        : this.onKeyUp(text).pipe(
          map(result => {
           this.spinnerService.end(); // stop loading spinner.
          if (results.data) {
              return results.data; // return list of item names for the dropdown.
          }
      })
        )));
  }

  onKeyUp(text: string): Observable<any> {
      this.spinnerService.start(); // start loading spinner animation overlay on the page.
      return this.http.post(this.apiUrlString, { 'itemName': text }); // this search request works fine.
  }
```
<p>The HTML, in case it is relevant:</p>
<pre class="lang-html prettyprint-override"><code>    <div>
      <input
        id="itemSearchValue"
        type="text"
        class="form-control/bg-light/rounded/dropdown-toggle"
        [(ngModel)]="selectedItem"
        (selectItem)="onSelectItem($event)" // irrelevant to the question.
        formControlName="itemSearchValue"
        [ngbTypeahead]="search"
        #instance="ngbTypeahead" />
    </div>
</code>```

How can I make sure the request is not cancelled by the browser when the user emits clicks somewhere? I'd like to keep the switchMap() method.

答:
Looks like all subscriptions are being cancelled onBlur

From the github: https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts

  handleBlur() {
    this._resubscribeTypeahead.next(null);
    this._onTouched();
  }
```
<p>So the solution is to not let the type-ahead have access to the network request subscription. Just subscribe within the component and pass a reference to the data instead.</p>
<pre class="lang-js prettyprint-override"><code>  data: string[] = [];
  sub = new Subscription();

  search = (input: Observable<string>) => {
    return input.pipe(
      debounceTime(500), // half second buffer before request starts
      distinctUntilChanged(),
      switchMap((text) => {
        if (text.length < 2) {
          this.clearDropDown(); // clear dropdown showing list of item names.
          return [];
        }
        this.subscribeToKeyUp(text); // update data
        return [this.data];
      })
    );
  };

  subscribeToKeyUp(text: string) {
    this.sub.unsubscribe(); // cancel if a request is still going
    this.spinnerService.start(); // start loading spinner animation overlay on the page.
    this.sub = this.onKeyUp(text).subscribe((results) => {
      if (results?.data) this.data = results.data;
      this.spinnerService.end(); // stop loading spinner.
    });
  }

  onKeyUp(text: string): Observable<any> {
    return this.http.post(this.apiUrlString, { itemName: text });
  }
</code>```

Here's a stackblitz that simulates a 3 second delay between request and response. Clicking off between the half second debounce time and the 3 second response still allows the request to complete.

https://stackblitz.com/edit/angular-cgyadh?file=src/app/typeahead-basic.ts

P.S. I saw that you mentioned requests can take 30+ seconds, in that case I'd make a button to call subscribeToKeyUp(text) and remove that call from the search function. That way the massive request doesn't get triggered on every letter. Just a suggestion anyway.

ContentLicense: CC BY-SA 4.0

Body:
I am new to RxJS (and frontend) but I know that switchMap() in the following code is used to break and re-run a search request as the user types into a text box. Search works fine, the only problem is that if the user clicks anywhere outside the textbox (like anywhere on the page, or on a different browser tab or window, or chrome devtools) after entering the text and before the request is fulfilled, the browser cancels the search request altogether.

(Note: The search request is cancelled and re-run correctly if user keeps typing while the request is being processed. Only click event causes the complete request cancellation without re-run)

  search = (input: Observable<string>) => {
    return input.pipe(
      debounceTime(500),
      distinctUntilChanged(),
      switchMap((text) => text.length < 2 ? this.clearDropDown() // clear dropdown showing list of item names.
        : this.onKeyUp(text).pipe(
          map(result => {
           this.spinnerService.end(); // stop loading spinner.
          if (results.data) {
              return results.data; // return list of item names for the dropdown.
          }
      })
        )));
  }

  onKeyUp(text: string): Observable<any> {
      this.spinnerService.start(); // start loading spinner animation overlay on the page.
      return this.http.post(this.apiUrlString, { 'itemName': text }); // this search request works fine.
  }

The HTML, in case it is relevant:

      <input
        id="itemSearchValue"
        type="text"
        class="form-control/bg-light/rounded/dropdown-toggle"
        [(ngModel)]="selectedItem"
        (selectItem)="onSelectItem($event)" // irrelevant to the question.
        formControlName="itemSearchValue"
        [ngbTypeahead]="search"
        #instance="ngbTypeahead" />

How can I make sure the request is not cancelled by the browser when the user emits clicks somewhere? I'd like to keep the switchMap() method.

Body:
Looks like all subscriptions are being cancelled onBlur

From the github: https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts

  handleBlur() {
    this._resubscribeTypeahead.next(null);
    this._onTouched();
  }

So the solution is to not let the type-ahead have access to the network request subscription. Just subscribe within the component and pass a reference to the data instead.

  data: string[] = [];
  sub = new Subscription();

  search = (input: Observable<string>) => {
    return input.pipe(
      debounceTime(500), // half second buffer before request starts
      distinctUntilChanged(),
      switchMap((text) => {
        if (text.length < 2) {
          this.clearDropDown(); // clear dropdown showing list of item names.
          return [];
        }
        this.subscribeToKeyUp(text); // update data
        return [this.data];
      })
    );
  };

  subscribeToKeyUp(text: string) {
    this.sub.unsubscribe(); // cancel if a request is still going
    this.spinnerService.start(); // start loading spinner animation overlay on the page.
    this.sub = this.onKeyUp(text).subscribe((results) => {
      if (results?.data) this.data = results.data;
      this.spinnerService.end(); // stop loading spinner.
    });
  }

  onKeyUp(text: string): Observable<any> {
    return this.http.post(this.apiUrlString, { itemName: text });
  }

Here's a stackblitz that simulates a 3 second delay between request and response. Clicking off between the half second debounce time and the 3 second response still allows the request to complete.

https://stackblitz.com/edit/angular-cgyadh?file=src/app/typeahead-basic.ts

P.S. I saw that you mentioned requests can take 30+ seconds, in that case I'd make a button to call subscribeToKeyUp(text) and remove that call from the search function. That way the massive request doesn't get triggered on every letter. Just a suggestion anyway.


问:
NOT NULL constraint failed: spring_post.publisher_id
I created a class base create view.When i try to submite the post model create view. it will return
NOT NULL constraint failed: spring_post.publisher_id
how can i set the publisher the get the current logged in user and set it to the post piblisher field.
im a beginner
this is the publisher field in my post model

```<code>    publisher=models.ForeignKey(User,on_delete=models.PROTECT)
#and this is my views
class PostCreateView(LoginRequiredMixin,CreateView):
    model=Post
    fields=['title','description']
    redirect_field_name="login"
</code>```

答:
You need to set the .publisher of the post, so:

```<code>class PostCreateView(LoginRequiredMixin,CreateView):
    model=Post
    fields = ['title','description']
    redirect_field_name = 'login'

    def form_valid(self, form):
        form.instance<strong>.publisher = self.request.user</strong>
        return super().form_valid(form)</code>```

You probably should also specify the success_url [Django-doc] to specify where to redirect to if the POST request was successful.

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Body:
I created a class base create view.When i try to submite the post model create view. it will return
NOT NULL constraint failed: spring_post.publisher_id
how can i set the publisher the get the current logged in user and set it to the post piblisher field.
im a beginner
this is the publisher field in my post model

    publisher=models.ForeignKey(User,on_delete=models.PROTECT)
#and this is my views
class PostCreateView(LoginRequiredMixin,CreateView):
    model=Post
    fields=['title','description']
    redirect_field_name="login"

Body:
You need to set the .publisher of the post, so:

class PostCreateView(LoginRequiredMixin,CreateView):
    model=Post
    fields = ['title','description']
    redirect_field_name = 'login'

    def form_valid(self, form):
        form.instance.publisher = self.request.user
        return super().form_valid(form)

You probably should also specify the success_url [Django-doc] to specify where to redirect to if the POST request was successful.

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


问:
Clickable region of JS+CSS animated button is cut off on Squarespace but not on CodePen
The + button on this page of my portfolio site provides more context and information on videos. It's composed of a simple "plus"-shaped SVG that I made contained within a circle-shaped div (border-radius: 100%), and animates out an additional div upon click.

On CodePen, where I originally coded this, the entire button (constituting both divs) is clickable. When I copied the code over to Squarespace, I noticed the upper half of the button is no longer clickable.

Since it works as intented on CodePen, I don't think there's an issue with the code (some relevant portions below but all is more easily visible in the CodePen link.

// HTML snippet:

```<code>    <body>
     <div id="feed">
      <section class="slide" id="bB1">
       <div class="containerBox cBBefore">
        <div class="textContainer">
          <div class="textSubCont">
            <div class="plusButton noSelect">
              <div class="plusSpan inactivePlus"></div>
            </div>
              </div>
          </div>
         </div>
       </section>
</code>```

// CSS Snippet:

```<code>    .plusButton {
     position: absolute;
     pointer-events: auto;
     cursor: default;
     box-sizing: content-box;
     border-radius: 100%;
     right: -1.333vmin;
     top: -1.333vmin;
     height: 5vmin;
     width: 5vmin;
     z-index: 6;
     background: rgba(79, 76, 220, 0.75);
     -webkit-filter: drop-shadow(
     -0.25vmin 0.5vmin 0.5vmin rgba(0, 0, 0, 0.33)) !important;
     filter: drop-shadow(-0.25vmin 0.5vmin 0.5vmin rgba(0, 0, 0, 0.33)) !important;
     }

    .plusSpan {
      content: url(https://www.charliemoody.com/s/plus.svg);
      width: 100%;
      height: 100%;
      transform-origin: center;
      -webkit-transform-origin: center;
     }

   .activePlus {
     -webkit-transform: rotate(-765deg);
     transform: rotate(-765deg);
     -webkit-transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     }

   .inactivePlus {
     -webkit-transform: rotate(0);
     transform: rotate(0);
     -webkit-transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     }
</code>```

// JS snippets

```<code>   function enableButtons() {
     let allButtons = document.querySelectorAll(".plusButton");
     let allButtonSpans = document.querySelectorAll(".plusSpan");
     let allCBs = document.querySelectorAll(".containerBox");

     for (let i = 0; i < allButtons.length; i++) {
      allButtons[i].addEventListener("click", function classToggle() {
      allButtonSpans[i].classList.toggle("inactivePlus");
      allButtonSpans[i].classList.toggle("activePlus");
      }
     }

    function pauseOnPlus() {
      let plusButtons = document.querySelectorAll(".plusButton");
      let vids = document.querySelectorAll(".vidElement");
      for (let i = 0; i < plusButtons.length; i++) {
      plusButtons[i].addEventListener("click", function (event) {
       if (vids[i].paused) vids[i].play();
       else vids[i].pause();
      });
     }
    }

    function loadTheRest() {
     enableButtons();
     pauseOnPlus();
    }

    window.addEventListener("load", loadTheRest);
</code>```

答: Nevermind!! Easy fix. Just needed to add "box-sizing: content-box;" to .plusSpan in the CSS.</p>

Body:
The + button on this page of my portfolio site provides more context and information on videos. It's composed of a simple "plus"-shaped SVG that I made contained within a circle-shaped div (border-radius: 100%), and animates out an additional div upon click.

On CodePen, where I originally coded this, the entire button (constituting both divs) is clickable. When I copied the code over to Squarespace, I noticed the upper half of the button is no longer clickable.

Since it works as intented on CodePen, I don't think there's an issue with the code (some relevant portions below but all is more easily visible in the CodePen link.

// HTML snippet:

// CSS Snippet:

    .plusButton {
     position: absolute;
     pointer-events: auto;
     cursor: default;
     box-sizing: content-box;
     border-radius: 100%;
     right: -1.333vmin;
     top: -1.333vmin;
     height: 5vmin;
     width: 5vmin;
     z-index: 6;
     background: rgba(79, 76, 220, 0.75);
     -webkit-filter: drop-shadow(
     -0.25vmin 0.5vmin 0.5vmin rgba(0, 0, 0, 0.33)) !important;
     filter: drop-shadow(-0.25vmin 0.5vmin 0.5vmin rgba(0, 0, 0, 0.33)) !important;
     }

    .plusSpan {
      content: url(https://www.charliemoody.com/s/plus.svg);
      width: 100%;
      height: 100%;
      transform-origin: center;
      -webkit-transform-origin: center;
     }

   .activePlus {
     -webkit-transform: rotate(-765deg);
     transform: rotate(-765deg);
     -webkit-transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     }

   .inactivePlus {
     -webkit-transform: rotate(0);
     transform: rotate(0);
     -webkit-transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     transition: transform 1s cubic-bezier(0.5, 0, 0.25, 1);
     }

// JS snippets

   function enableButtons() {
     let allButtons = document.querySelectorAll(".plusButton");
     let allButtonSpans = document.querySelectorAll(".plusSpan");
     let allCBs = document.querySelectorAll(".containerBox");

     for (let i = 0; i < allButtons.length; i++) {
      allButtons[i].addEventListener("click", function classToggle() {
      allButtonSpans[i].classList.toggle("inactivePlus");
      allButtonSpans[i].classList.toggle("activePlus");
      }
     }

    function pauseOnPlus() {
      let plusButtons = document.querySelectorAll(".plusButton");
      let vids = document.querySelectorAll(".vidElement");
      for (let i = 0; i < plusButtons.length; i++) {
      plusButtons[i].addEventListener("click", function (event) {
       if (vids[i].paused) vids[i].play();
       else vids[i].pause();
      });
     }
    }

    function loadTheRest() {
     enableButtons();
     pauseOnPlus();
    }

    window.addEventListener("load", loadTheRest);


问:
Using onclick to change 6 circles into different shapes and back to a circle once clicked again
Code is very basic as I'm only a beginner.  Can't understand what I'm to do within my function to preform this.Not sure if I need to use a loop to preform this or can I can do this with just the onclick and a function to pass the parameter to? Not sure if the array is needed or not? Thought I'd have to have some sort of an index to refer to for the function to know which shape the circle is to change to</p>
```<code><html lang="en">
    <head>

   <script>

function changeShape(){

array for the shapes
 var shapes = new Array;
        shapes["circle"] = "circle";
        shapes["square"] = "square";
        shapes["triangle"] = "triangle";
        shapes["parall"] = "parall";
        shapes["trap"] = "trap";

     document.getElementById("shape1").className=="circle";

}
        }

        </script>

        <meta charset = "UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>Document</title>

    </head>

    <body>
        <div id="shape1" class = "circle" onclick="changeShape('shape1')"></div>

        <br>
        <div id="shape2" class="square" onclick="changeShape('shape2')"></div>
        <br>
        <div id="shape3" class="oval" onclick="changeShape('shape3')"></div>
        <br>
        <div id="shape4" class="rectangle" onclick="changeShape('shape4')"></div>
        <br>
        <div id="shape5" class="triangle" onclick="changeShape('shape5')"></div>
        <br>
        <div id="shape6" class="parall" onclick="changeShape('shape6')"></div>
        <br>
        <div id="shape7" class="trap" onclick="changeShape('shape7')"></div>
        <br>

    </body>
<style>

    *{
      padding:0;
        margin: 0;
        box-sizing: border-box;

    }

    .circle{

        width:200px;
        height: 200px;
           border-radius: 50%;
        background: red;
    }

    .square{

        width:200px;
        height: 200px;

        background: orange;
    }

    .oval{
        padding: 5%;
        width:300px;
        height: 100px;
           border-radius: 45%;
        background: yellow;
    }

    .rectangle{

        width:350px;
        height: 150px;

        background: green;
    }

    .triangle{

     width: 0;
    height: 0;
    border-left: 25px solid transparent;
    border-right: 25px solid transparent;
    border-bottom: 50px solid #555;

    }

    .parall {
    width: 100px;
    height: 50px;
    transform: skew(20deg);
    background: #555;
}

    .trap {
    border-bottom: 50px solid #555;
    border-left: 25px solid transparent;
    border-right: 25px solid transparent;
    height: 0;
    width: 125px;
}

    </style>

</html>```
</code>```

答:
Use this changeShape function instead:</p>
```<code>function changeShape(shape){
var shapes={"shape1":"circle","shape2":"sqare","shape3":"oval","shape4":"rectangle","shape5":"triangle","shape6":"parall","shape7":"trap"};
var element=document.getElementById(shape);
if (element.className=="circle"){
element.className=shapes[shape];
}
else{
element.className="circle";
}
}
</code>```

Body:
Code is very basic as I'm only a beginner.  Can't understand what I'm to do within my function to preform this.Not sure if I need to use a loop to preform this or can I can do this with just the onclick and a function to pass the parameter to? Not sure if the array is needed or not? Thought I'd have to have some sort of an index to refer to for the function to know which shape the circle is to change to

        <meta charset = "UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>Document</title>

```

Body:
Use this changeShape function instead:

function changeShape(shape){
var shapes={"shape1":"circle","shape2":"sqare","shape3":"oval","shape4":"rectangle","shape5":"triangle","shape6":"parall","shape7":"trap"};
var element=document.getElementById(shape);
if (element.className=="circle"){
element.className=shapes[shape];
}
else{
element.className="circle";
}
}


问:
Confirm my attempt at converting Crystal reports selection criteria to Oracle SQL
I have to create selection criteria for an Oracle SQL query based on a snippet from Crystal Reports.

I have no experience with Crystal reports so I have been trying to figure it out searching the web, but seem to be just wasting my time - Could not find anything helpful for this kind of task on the web.

This is the selection criteria that was provided:

```<code>{MATL_USED_VW.MAT_ID} = {?Material ID} and
{@Use Date} in {?Previous Use}
      //@UseDate = Date({MATERIAL_ACTIVITIES.MA_END})
</code>```

The column data types are all date columns except for the numeric MAT_ID column

I think this would equate to the following:

```<code>where matl_used_vw.mat_id = :Material_id
  and use_date in (:previous_use, :usedate)
</code>```

This is just a swag based on assumptions.

Here's my assumptions on the symbols:

? - probably is a parameter or prompt for input

@ -  has something to do with formulas

// - is continuation of previous line

{} - encloses an object (text, date number  or whatever)

I'm not sure of anything here, it's all just a guess.

If anyone could shed some light on this, I would really appreciate it!

答:
Thanks for the help on this!

Here's the answer in case some other schmuck unfamiliar with Crystal reports needs a similar answer:

@ is a Formula.  In this case, to convert text to date.

? is a Parameter  In this case it represents a range

// is a remark.  Same as # or ‘ in other languages.

{} - encloses an object (text, date number or whatever)

Body:
I have to create selection criteria for an Oracle SQL query based on a snippet from Crystal Reports.

I have no experience with Crystal reports so I have been trying to figure it out searching the web, but seem to be just wasting my time - Could not find anything helpful for this kind of task on the web.

This is the selection criteria that was provided:

{MATL_USED_VW.MAT_ID} = {?Material ID} and
{@Use Date} in {?Previous Use}
      //@UseDate = Date({MATERIAL_ACTIVITIES.MA_END})

The column data types are all date columns except for the numeric MAT_ID column

I think this would equate to the following:

where matl_used_vw.mat_id = :Material_id
  and use_date in (:previous_use, :usedate)

This is just a swag based on assumptions.

Here's my assumptions on the symbols:

? - probably is a parameter or prompt for input

@ -  has something to do with formulas

// - is continuation of previous line

{} - encloses an object (text, date number  or whatever)

I'm not sure of anything here, it's all just a guess.

If anyone could shed some light on this, I would really appreciate it!


问:
How to Reduce redundant code of If-Else Statements in Python
How to Reduce Code Duplication of If-Else Statements in Python from below function. Also, which specific exception can i raise here?</p>
```<code>def get_table_id_and_gcp_path(source, database, table, dc, env, date_folder):
    try:
        table_id=f"{database}_stg.{table}"
        gcp_path = f"gs://{env}/{database}/{table}/"
        if dc != '-1':
            table_id = table_id + '_' + dc + '_stg'
            gcp_path = gcp_path + dc + "/dt=" + date_folder + "/*.parquet"
        else:
            table_id = table_id + '_stg'
            gcp_path = gcp_path + "dt=" + date_folder + "/*.parquet"

    except Exception as e:
        print(e)
        raise

    return table_id, gcp_path
</code>```

答:
Answer to the first part

```<code>   if dc != '-1':
        sep = '_'
   else:
        sep = ''
        dc = '/'

   table_id = table_id + sep + dc + '_stg'
   gcp_path = gcp_path + dc + "dt=" + date_folder + "/*.parquet"
</code>```

I don't know what type of exception you can raise.  You could have anything from dc not being a string to gcp path no existing.

Body:
How to Reduce Code Duplication of If-Else Statements in Python from below function. Also, which specific exception can i raise here?

def get_table_id_and_gcp_path(source, database, table, dc, env, date_folder):
    try:
        table_id=f"{database}_stg.{table}"
        gcp_path = f"gs://{env}/{database}/{table}/"
        if dc != '-1':
            table_id = table_id + '_' + dc + '_stg'
            gcp_path = gcp_path + dc + "/dt=" + date_folder + "/*.parquet"
        else:
            table_id = table_id + '_stg'
            gcp_path = gcp_path + "dt=" + date_folder + "/*.parquet"

    except Exception as e:
        print(e)
        raise

    return table_id, gcp_path

Body:
Answer to the first part

   if dc != '-1':
        sep = '_'
   else:
        sep = ''
        dc = '/'

   table_id = table_id + sep + dc + '_stg'
   gcp_path = gcp_path + dc + "dt=" + date_folder + "/*.parquet"

I don't know what type of exception you can raise.  You could have anything from dc not being a string to gcp path no existing.


问:
Serial communication with Uponor Smatrix Base X-245
I'm trying to communicate with a Uponor Smatrix Base X-245 using a use a Raspberry Pi 3B+ over the serial port (UART), without much luck.

Here is a sample output from the UART (/dev/ttyS0) using pyserial:

import serial
ser = serial.Serial("/dev/ttyS0", baudrate=19200)
while True:
    received_data = ser.read()
    sleep(0.025)
    data_left = ser.inWaiting()
    received_data += ser.read(data_left)
    print (received_data.hex())
```
<p>Data without any thermostats (8) connected:</p>
```00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
dd  e7  c9  6b  01  0a  2e  fe
dd  e7  af  83  01  56  89  ff
dd  e7  f5  33  01  bf  36  fe
dd  e7  f7  6d  01  ce  f6  fe
dd  e7  f7  2b  01  aa  36  fe
dd  e7  f7  75  01  da  f6  fe
dd  e7  f7  49  01  fe  76  ff
dd  e7  f5  45  01  99  f6  fe
```
<p>Data with all thermostats (8) connected:</p>
```00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
dd  e7  c9  6b  01  0a  2e  fe  77  5e  6e  e3  ed  db  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  3d  7b  99  ff  75  53  fe
dd  e7  c9  6b  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  3d  87  ff  6f  95  ff  ff  8d  2f  ff
dd  e7  af  83  01  56  89  ff  77  de  6d  e4  ed  cb  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  85  7b  99  ff  0b  07  ff
dd  e7  af  83  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  85  87  ff  6f  95  ff  ff  25  3b  fe
dd  e7  f5  33  01  bf  36  fe  77  5e  df  d3  ed  eb  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  85  7b  99  ff  71  0f  ff
dd  e7  f5  33  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  85  87  ff  6f  95  ff  ff  d3  fb  ff
dd  e7  f7  6d  01  ce  f6  fe  f7  fe  fc  fe
dd  e7  f7  6d  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  79  87  ff  6f  95  ff  ff  15  d3  fe
dd  e7  f7  2b  01  aa  36  fe
dd  e7  f7  2b  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  67  87  ff  6f  95  ff  ff  43  91  ff
dd  e7  f7  75  01  da  f6  fe  77  de  5f  c7  ed  97  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  07  7b  99  ff  cf  8f  fe
dd  e7  f7  75  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  07  87  ff  6f  95  ff  ff  77  9b  ff
dd  e7  f7  49  01  fe  76  ff  77  de  5f  e2  ed  7b  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  79  7b  99  ff  95  ff  ff
dd  e7  f7  49  a5  01  01  85  ff  7f  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  79  87  ff  6f  95  ff  ff  c1  3   ff
dd  e7  f5  45  01  99  f6  fe  77  5e  5f  d4  ed  bb  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  3d  7b  99  ff  bb  d1  ff
dd  e7  f5  45  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  3d  87  ff  6f  95  ff  ff  bf  0d  ff
```
<p>Included here the same data, but color coded to recognize patterns.</p>
<p>Also the raw bytes that were captured:</p>
```00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
dd e7 c9 k  01 \n .  fe w  ^  n  e3 ed f7 83 ff ff 81 e7 fb {  99 ff -  1f fe
dd e7 c9 k  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb =  87 ff o  95 ff ff 8d /  ff

dd e7 af 83 01 V  89 ff w  de m  e4 ed cb 83 ff ff 81 e7 fb {  99 ff e9 d1 ff
dd e7 af 83 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff o  95 ff ff %  ;  fe

dd e7 f5 3  01 bf 6  fe w  ^  df d3 ed e5 83 ff ff 81 e7 fb {  99 ff 93 a7 fe
dd e7 f5 3  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff o  95 ff ff d3 fb ff

dd e7 f7 m  01 ce f6 fe ff ff ff ff `  ff ff
dd e7 f7 m  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb y  87 ff o  95 ff ff 15 d3 fe

dd e7 f7 +  01 aa 6  fe
dd e7 f7 +  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb w  87 ff o  95 ff ff Q  11 ff

dd e7 f7 u  01 da f6 fe w  de _  c7 ed ?  87 ff ff 81 e7 fb {  99 ff bd i  ff
dd e7 f7 u  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 07 87 ff o  95 ff ff w  9b ff

dd e7 f7 I  01 fe v  ff w  de _  e2 ed u  83 ff ff 81 e7 fb {  99 ff cf a1 ff
dd e7 f7 I  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb y  87 ff o  95 ff ff eb 9d ff

dd e7 f5 E  01 99 f6 fe w  ^  _  d4 ed a7 83 ff ff 81 e7 fb {  99 ff 85 0f ff
dd e7 f5 E  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb =  87 ff o  95 ff ff bf \r ff
```
<h2>Base station</h2>
<p>Uponor Smatrix Base X-245. Some sites claim it communicates over RS485. Do not confuse with the PRO version that supports Modbus.</p>
<h2>Thermostat</h2>
<p>The thermostats are Uponor Smatrix Base T-146 Bus, which have a Renesas RL78/L13 chipset which is used for serial communication (I think). From the datasheet:</p>
<blockquote>
<p>[80-pin]<br />
• CSI: 1 channel/UART (UART supporting LIN-bus): 1 channel/simplified I2C: 1 channel<br />
• CSI: 1 channel/UART: 1 channel/simplified I2C: 1 channel<br />
• UART: 2 channels</p>
</blockquote>
<h2>Setup</h2>
```Raspberry Pi 3B+         X-245        T-146
GPIO 14 (UART TX)  <-->    A    <-->    A
GPIO 15 (UART RX)  <-->    B    <-->    B
                           +    <-->    +
                           -    <-->    -
```

Who recognizes a protocol or can help me decode it? I've tried:

RS485/Modbus: Can't get a response, probably there is no modbus master/slave

LIN-bus: Can't see the 0x55 byte anywhere

I2C: i2cdetect -y 1 doesn't return an address

答:
So it turns out that I was missing a TTL > RS485 converter, so I added that and now I can clearly read the data, and it turns out to be Modbus after all. This article helped me to setup a stable serial reader and this one helped me to get to the Modbus result. This is the output now:

```<code>110c28beff6abb
110c28be4002753e00003f0c0242b3003f71
110c28be2d7fff3d00000c002437019a3803b63b023c3c0048358000fd22
110c0566ffa0b2
110c05664002623e00003f0c0242b30082ca
110c05662d7fff3d00000c002437019a3803b63b024e3c004835800054c5
110c04c9ff8c82
110c04c94002c53e00003f0c0242b300a1fd
110c04c92d7fff3d00000c002437019a3803b63b02c43c00483580008356
110c04eaff95b2
110c04ea4002c43e00003f0c0242b3008a9b
110c04ea2d7fff3d00000c002437019a3803b63b02c43c0048358000d777
110c04c5ff8982
110c04c54002a03e00003f0c0242b300a39f
110c04c52d7fff3d00000c002437019a3803b63b027c3c00483580004432
110c04dbff8022
110c04db4002c73e00003f0c0242b30039e5
110c04db2d7fff3d00000c002437019a3803b63b02c33c00483580000ab1
110c055dffb382
110c055d4002843e00003f0c0242b3003df8
110c055d2d7fff3d00000c002437019a3803b63b027c3c0048358000edf8
</code>```

Now that I have a readable result, I do have another problem:
The serial bus keeps sending the event log for all thermostats i.e. function code 12 (0x0C) Get Comm Event Log. I have no idea how to get rid of this as all the responses start with \x11\x0c minimalmobus can't match a request to the right slave (\x11 will be slave number 17, while I request data from slave number 1). What to do here?

minimalmodbus config

```<code>import minimalmodbus
from gpiozero import OutputDevice
de = OutputDevice(23)
re = OutputDevice(24)
de.off()
re.off()
instrument = minimalmodbus.Instrument('/dev/serial0', 1, minimalmodbus.MODE_RTU)
instrument.serial.timeout = None
instrument.debug = True
</code>```

read_register output

```<code>>>> instrument.read_register(40006,0,3,True)
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 9C 46 00 01 4B 8F (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/serial0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 2965.81 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: 11 0C 1B CA FF BD B4 (7 bytes), roundtrip time: 7.0 ms. Timeout for reading: 0.0 ms.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 486, in read_register
    payloadformat=_Payloadformat.REGISTER,
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1245, in _generic_command
    payload_from_slave = self._perform_command(functioncode, payload_to_slave)
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1330, in _perform_command
    response, self.address, self.mode, functioncode
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1875, in _extract_payload
    responseaddress, slaveaddress, response
minimalmodbus.InvalidResponseError: Wrong return slave address: 17 instead of 1. The response is: '\x11\x0c\x1bÊÿ½´'
</code>```

Do you guys know what to do? Is it possible that the Uponor Smatrix Base X-245 only has a subset of the Modbus functions implemented? If so, what would my best shot be to write something back?

I tried to capture a possible request to change the temperature by adjusting it on the thermostat, but all I can see is the log where I went from 21,5°C (707°K, \x02\xc4) to 25,0°C (770°K, \x03\x02)

```<code>110c04eaff95b2
110c04ea4002c43e00003f0c02 42b3008a9b
110c04ea2d7fff3d00000c002437019a3803b63b02c43c0048358000d777

110c04eaff95b2
110c04ea4002c43e00003f0c02 3c00483b030242b3004466
110c04ea2d7fff3d00000c002437019a3803b63b03023c0048358000b0b7

110c04eaff95b2
110c04ea4002c43e00003f0c023c00483b030242b3004466
110c04ea2d7fff3d00400c002437019a3803b63b03023c0048358000a578

110c04eaff95b2
110c04ea4002c43e00003f0c0242b3008a9b
110c04ea2d7fff3d00400c002437019a3803b63b03023c0048358000a578
</code>```

Body:
I'm trying to communicate with a Uponor Smatrix Base X-245 using a use a Raspberry Pi 3B+ over the serial port (UART), without much luck.

Here is a sample output from the UART (/dev/ttyS0) using pyserial:

import serial
ser = serial.Serial("/dev/ttyS0", baudrate=19200)
while True:
    received_data = ser.read()
    sleep(0.025)
    data_left = ser.inWaiting()
    received_data += ser.read(data_left)
    print (received_data.hex())

Data without any thermostats (8) connected:

00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
dd  e7  c9  6b  01  0a  2e  fe
dd  e7  af  83  01  56  89  ff
dd  e7  f5  33  01  bf  36  fe
dd  e7  f7  6d  01  ce  f6  fe
dd  e7  f7  2b  01  aa  36  fe
dd  e7  f7  75  01  da  f6  fe
dd  e7  f7  49  01  fe  76  ff
dd  e7  f5  45  01  99  f6  fe

Data with all thermostats (8) connected:

00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
00  00  00  00  00  00  00  00  00  00  00  00  00  00  c0
dd  e7  c9  6b  01  0a  2e  fe  77  5e  6e  e3  ed  db  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  3d  7b  99  ff  75  53  fe
dd  e7  c9  6b  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  3d  87  ff  6f  95  ff  ff  8d  2f  ff
dd  e7  af  83  01  56  89  ff  77  de  6d  e4  ed  cb  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  85  7b  99  ff  0b  07  ff
dd  e7  af  83  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  85  87  ff  6f  95  ff  ff  25  3b  fe
dd  e7  f5  33  01  bf  36  fe  77  5e  df  d3  ed  eb  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  85  7b  99  ff  71  0f  ff
dd  e7  f5  33  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  85  87  ff  6f  95  ff  ff  d3  fb  ff
dd  e7  f7  6d  01  ce  f6  fe  f7  fe  fc  fe
dd  e7  f7  6d  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  79  87  ff  6f  95  ff  ff  15  d3  fe
dd  e7  f7  2b  01  aa  36  fe
dd  e7  f7  2b  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  67  87  ff  6f  95  ff  ff  43  91  ff
dd  e7  f7  75  01  da  f6  fe  77  de  5f  c7  ed  97  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  07  7b  99  ff  cf  8f  fe
dd  e7  f7  75  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  07  87  ff  6f  95  ff  ff  77  9b  ff
dd  e7  f7  49  01  fe  76  ff  77  de  5f  e2  ed  7b  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  79  7b  99  ff  95  ff  ff
dd  e7  f7  49  a5  01  01  85  ff  7f  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  79  87  ff  6f  95  ff  ff  c1  3   ff
dd  e7  f5  45  01  99  f6  fe  77  5e  5f  d4  ed  bb  83  ff  ff  81  e7  fb  87  ff  6f  89  fb  3d  7b  99  ff  bb  d1  ff
dd  e7  f5  45  a5  01  01  85  ff  ff  e7  ff  b7  91  fd  cb  8f  f9  93  89  fb  3d  87  ff  6f  95  ff  ff  bf  0d  ff

Included here the same data, but color coded to recognize patterns.

Also the raw bytes that were captured:

00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
dd e7 c9 k  01 \n .  fe w  ^  n  e3 ed f7 83 ff ff 81 e7 fb {  99 ff -  1f fe
dd e7 c9 k  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb =  87 ff o  95 ff ff 8d /  ff

dd e7 af 83 01 V  89 ff w  de m  e4 ed cb 83 ff ff 81 e7 fb {  99 ff e9 d1 ff
dd e7 af 83 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff o  95 ff ff %  ;  fe

dd e7 f5 3  01 bf 6  fe w  ^  df d3 ed e5 83 ff ff 81 e7 fb {  99 ff 93 a7 fe
dd e7 f5 3  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff o  95 ff ff d3 fb ff

dd e7 f7 m  01 ce f6 fe ff ff ff ff `  ff ff
dd e7 f7 m  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb y  87 ff o  95 ff ff 15 d3 fe

dd e7 f7 +  01 aa 6  fe
dd e7 f7 +  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb w  87 ff o  95 ff ff Q  11 ff

dd e7 f7 u  01 da f6 fe w  de _  c7 ed ?  87 ff ff 81 e7 fb {  99 ff bd i  ff
dd e7 f7 u  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 07 87 ff o  95 ff ff w  9b ff

dd e7 f7 I  01 fe v  ff w  de _  e2 ed u  83 ff ff 81 e7 fb {  99 ff cf a1 ff
dd e7 f7 I  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb y  87 ff o  95 ff ff eb 9d ff

dd e7 f5 E  01 99 f6 fe w  ^  _  d4 ed a7 83 ff ff 81 e7 fb {  99 ff 85 0f ff
dd e7 f5 E  a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb =  87 ff o  95 ff ff bf \r ff

Base station

Uponor Smatrix Base X-245. Some sites claim it communicates over RS485. Do not confuse with the PRO version that supports Modbus.

Thermostat

The thermostats are Uponor Smatrix Base T-146 Bus, which have a Renesas RL78/L13 chipset which is used for serial communication (I think). From the datasheet:

[80-pin]

• CSI: 1 channel/UART (UART supporting LIN-bus): 1 channel/simplified I2C: 1 channel

• CSI: 1 channel/UART: 1 channel/simplified I2C: 1 channel

• UART: 2 channels

Setup

Raspberry Pi 3B+         X-245        T-146
GPIO 14 (UART TX)  <-->    A    <-->    A
GPIO 15 (UART RX)  <-->    B    <-->    B
                           +    <-->    +
                           -    <-->    -

Who recognizes a protocol or can help me decode it? I've tried:

RS485/Modbus: Can't get a response, probably there is no modbus master/slave

LIN-bus: Can't see the 0x55 byte anywhere

I2C: i2cdetect -y 1 doesn't return an address

Body:
So it turns out that I was missing a TTL > RS485 converter, so I added that and now I can clearly read the data, and it turns out to be Modbus after all. This article helped me to setup a stable serial reader and this one helped me to get to the Modbus result. This is the output now:

110c28beff6abb
110c28be4002753e00003f0c0242b3003f71
110c28be2d7fff3d00000c002437019a3803b63b023c3c0048358000fd22
110c0566ffa0b2
110c05664002623e00003f0c0242b30082ca
110c05662d7fff3d00000c002437019a3803b63b024e3c004835800054c5
110c04c9ff8c82
110c04c94002c53e00003f0c0242b300a1fd
110c04c92d7fff3d00000c002437019a3803b63b02c43c00483580008356
110c04eaff95b2
110c04ea4002c43e00003f0c0242b3008a9b
110c04ea2d7fff3d00000c002437019a3803b63b02c43c0048358000d777
110c04c5ff8982
110c04c54002a03e00003f0c0242b300a39f
110c04c52d7fff3d00000c002437019a3803b63b027c3c00483580004432
110c04dbff8022
110c04db4002c73e00003f0c0242b30039e5
110c04db2d7fff3d00000c002437019a3803b63b02c33c00483580000ab1
110c055dffb382
110c055d4002843e00003f0c0242b3003df8
110c055d2d7fff3d00000c002437019a3803b63b027c3c0048358000edf8

Now that I have a readable result, I do have another problem:
The serial bus keeps sending the event log for all thermostats i.e. function code 12 (0x0C) Get Comm Event Log. I have no idea how to get rid of this as all the responses start with \x11\x0c minimalmobus can't match a request to the right slave (\x11 will be slave number 17, while I request data from slave number 1). What to do here?

minimalmodbus config

import minimalmodbus
from gpiozero import OutputDevice
de = OutputDevice(23)
re = OutputDevice(24)
de.off()
re.off()
instrument = minimalmodbus.Instrument('/dev/serial0', 1, minimalmodbus.MODE_RTU)
instrument.serial.timeout = None
instrument.debug = True

read_register output

>>> instrument.read_register(40006,0,3,True)
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 9C 46 00 01 4B 8F (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/serial0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 2965.81 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: 11 0C 1B CA FF BD B4 (7 bytes), roundtrip time: 7.0 ms. Timeout for reading: 0.0 ms.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 486, in read_register
    payloadformat=_Payloadformat.REGISTER,
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1245, in _generic_command
    payload_from_slave = self._perform_command(functioncode, payload_to_slave)
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1330, in _perform_command
    response, self.address, self.mode, functioncode
  File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1875, in _extract_payload
    responseaddress, slaveaddress, response
minimalmodbus.InvalidResponseError: Wrong return slave address: 17 instead of 1. The response is: '\x11\x0c\x1bÊÿ½´'

Do you guys know what to do? Is it possible that the Uponor Smatrix Base X-245 only has a subset of the Modbus functions implemented? If so, what would my best shot be to write something back?

I tried to capture a possible request to change the temperature by adjusting it on the thermostat, but all I can see is the log where I went from 21,5°C (707°K, \x02\xc4) to 25,0°C (770°K, \x03\x02)

110c04eaff95b2
110c04ea4002c43e00003f0c02 42b3008a9b
110c04ea2d7fff3d00000c002437019a3803b63b02c43c0048358000d777

110c04eaff95b2
110c04ea4002c43e00003f0c02 3c00483b030242b3004466
110c04ea2d7fff3d00000c002437019a3803b63b03023c0048358000b0b7

110c04eaff95b2
110c04ea4002c43e00003f0c023c00483b030242b3004466
110c04ea2d7fff3d00400c002437019a3803b63b03023c0048358000a578

110c04eaff95b2
110c04ea4002c43e00003f0c0242b3008a9b
110c04ea2d7fff3d00400c002437019a3803b63b03023c0048358000a578


问:
Calling a function from outside class with user input without using global
I am trying to avoid using global, instead I created a class. I am having trouble calling the class, instead, I am getting the following error

```<code>TypeError: phone.__init__() missing 1 required positional argument: 'NUMBER_INPUT'
</code>```

Any ideas? Thanks in advance!

```<code>class phone:

        def __init__(self,NUMBER_INPUT):
            self.NUMBER_INPUT = NUMBER_INPUT

        def phone_number(self):
            """validate user input of phone number"""
            while True:
                self.NUMBER_INPUT = input("Please enter your phone number: ")
                if  re.fullmatch(r"\d{3}-\d{3}-\d{4}" ,self.NUMBER_INPUT):
                    print("You phone number is: " + self.NUMBER_INPUT)
                    break
                print("Please enter a valid phone number ex. 123-456-5678")

    phone().phone_number()
</code>```

答:
So, I think you neither did read documentation nor watched/read any tutorial about Python classes. So I will explain it here for you.

Class is a "object project". It may have predefined methods, predefined values. It also may have a way to construct these dynamically.

Class object at first need to be instantiated and then initiated. That means that firstly you need to create an instance of a class, then to initiate default values.

Python has 2 methods for this.

__new__() creates a new instance of a class and returns it. It's already realised for every Python class, but there may be special cases for you to override it.

__init__(*args, **kwargs) initiates values of a class. You must define non-static values here or globally in class.

So, creating a class object is achieved in python by calling class like this

```<code>A_instance = A(*args, **kwargs)
</code>```

That in words means create me instance of A with these args and kwargs

So in your code, you are using (actualy overriding) __init__(*args, **kwargs) with args = (NUMBER_INPUT,) and kwargs = None.

Thus you must provide NUMBER_INPUT every time you create an object of phone, like so:

```<code>phone1 = phone("123-456-7890")
phone2 = phone("098-765-4321")
</code>```

Body:
I am trying to avoid using global, instead I created a class. I am having trouble calling the class, instead, I am getting the following error

TypeError: phone.__init__() missing 1 required positional argument: 'NUMBER_INPUT'

Any ideas? Thanks in advance!

class phone:

        def __init__(self,NUMBER_INPUT):
            self.NUMBER_INPUT = NUMBER_INPUT

        def phone_number(self):
            """validate user input of phone number"""
            while True:
                self.NUMBER_INPUT = input("Please enter your phone number: ")
                if  re.fullmatch(r"\d{3}-\d{3}-\d{4}" ,self.NUMBER_INPUT):
                    print("You phone number is: " + self.NUMBER_INPUT)
                    break
                print("Please enter a valid phone number ex. 123-456-5678")

    phone().phone_number()

Body:
So, I think you neither did read documentation nor watched/read any tutorial about Python classes. So I will explain it here for you.

Class is a "object project". It may have predefined methods, predefined values. It also may have a way to construct these dynamically.

Class object at first need to be instantiated and then initiated. That means that firstly you need to create an instance of a class, then to initiate default values.

Python has 2 methods for this.

__new__() creates a new instance of a class and returns it. It's already realised for every Python class, but there may be special cases for you to override it.

__init__(*args, **kwargs) initiates values of a class. You must define non-static values here or globally in class.

So, creating a class object is achieved in python by calling class like this

A_instance = A(*args, **kwargs)

That in words means create me instance of A with these args and kwargs

So in your code, you are using (actualy overriding) __init__(*args, **kwargs) with args = (NUMBER_INPUT,) and kwargs = None.

Thus you must provide NUMBER_INPUT every time you create an object of phone, like so:

phone1 = phone("123-456-7890")
phone2 = phone("098-765-4321")


问:
Salesforce standard objects accessibility based on org wide share settings and roles
Is there any possible way to fetch the SFDC standard objects such as Accounts, Opportunity, Contacts and Leads based on the accessiblty rules configured in the SFDC using REST API of SFDC? If yes, then how exactly we can pass the user specific details along with passing the admin users access key for connected-app.</p>

答:
So you want single login to API as system administrator but to run queries filtered by Salesforce as if user X would be asking, to take into account org wide defaults, sharing rules etc?

You might want to experiment with UserRecordAccess, simpler than checking AccountShare tables, traversing groups, all that mess. But you might have to do it in 2 steps.

This doesn't work:

```<code>SELECT RecordId
FROM UserRecordAccess
WHERE UserId = '005700000012zKY' AND HasReadAccess = true
AND RecordId IN (SELECT Id FROM Account)
</code>```

But this is promising

```<code>Set<Id> ids = new Map<Id, Account>([SELECT Id FROM Account LIMIT 200]).keyset();

System.debug([SELECT RecordId
    FROM UserRecordAccess
    WHERE UserId = '005700000012zKY' AND HasReadAccess = true
    AND RecordId IN :ids
]);
</code>```

(yes, there's some limit to 200 records)

If this feels too clunky maybe best would be to really not have admin account in the integration but let people log in to SF through your app and "naturally" fetch / edit only what they can see? For current user UserRecordAccess can be used directly in the main query, select id, name, userrecordaccess.haseditaccess from account. You could then even use "scopes" if you have fancy queues setup or territories.

Body:
So you want single login to API as system administrator but to run queries filtered by Salesforce as if user X would be asking, to take into account org wide defaults, sharing rules etc?

You might want to experiment with UserRecordAccess, simpler than checking AccountShare tables, traversing groups, all that mess. But you might have to do it in 2 steps.

This doesn't work:

SELECT RecordId
FROM UserRecordAccess
WHERE UserId = '005700000012zKY' AND HasReadAccess = true
AND RecordId IN (SELECT Id FROM Account)

But this is promising

Set<Id> ids = new Map<Id, Account>([SELECT Id FROM Account LIMIT 200]).keyset();

System.debug([SELECT RecordId
    FROM UserRecordAccess
    WHERE UserId = '005700000012zKY' AND HasReadAccess = true
    AND RecordId IN :ids
]);

(yes, there's some limit to 200 records)

If this feels too clunky maybe best would be to really not have admin account in the integration but let people log in to SF through your app and "naturally" fetch / edit only what they can see? For current user UserRecordAccess can be used directly in the main query, select id, name, userrecordaccess.haseditaccess from account. You could then even use "scopes" if you have fancy queues setup or territories.


问:
CMAKE_CXX_SOURCE_FILE_EXTENSIONS not working with thrust/cuda
Thrust allows for one to specify different backends at cmake configure time via the THRUST_DEVICE_SYSTEM flag.  My problem is that I have a bunch of .cu files that I want to be compiled as regular c++ files when a user runs cmake with -DTHRUST_DEVICE_SYSTEM=OMP (for example).  If I change the extension of the .cu files to .cpp they compile fine (indicating that I just need tell cmake to use the c++ compiler on the .cu files). But if I add .cu to CMAKE_CXX_SOURCE_FILE_EXTENSIONS then I get a CMake Error: Cannot determine link language for target "cuda_kernels".  Here's a minimal cmake example:

```<code>cmake_minimum_required(VERSION 3.19)

project(kernels LANGUAGES C CXX Fortran)

set(KERNELS_USE_OMP OFF)
if ("${THRUST_DEVICE_SYSTEM}" STREQUAL "OMP")
  set(KERNELS_USE_OMP ON)
endif()

# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT KERNELS_USE_OMP)
  enable_language(CUDA)
else()
  list(PREPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS "cu;CU")
endif()

message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")

find_package(Thrust REQUIRED CONFIG)
thrust_create_target(Thrust FROM_OPTIONS)

add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels Thrust)

</code>```

The output of the message command on my system is: -- cu;CU;C;M;c++;cc;cpp;cxx;mm;mpp;CPP;ixx;cppm

Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?

答:
Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?

The extension-to-language for <LANG> is set as soon as <LANG> is enabled by inspecting the value of the CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS variable when the language detection module exits.

Unfortunately, there is no blessed way to override this list for CXX as it is hard-coded in Modules/CMakeCXXCompiler.cmake.in.

Perhaps the best way of working around the actual error would be to use the LANGUAGE source file property to tell CMake how to compile the individual CUDA files, like so:

```<code>cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES CXX)

find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)

thrust_is_cuda_system_found(USE_CUDA)
if (USE_CUDA)
  enable_language(CUDA)
endif()

set(cuda_kernel_sources my_kernels.cu)

add_library(cuda_kernels ${cuda_kernel_sources})
target_link_libraries(cuda_kernels PRIVATE Thrust)

if (NOT USE_CUDA)
  set_source_files_properties(
    ${cuda_kernel_sources}
    PROPERTIES
    LANGUAGE CXX
  )
endif ()
</code>```

This will certainly be friendlier to other projects that might try to add_subdirectory yours.

However, if we want to be very naughty, we can do this:

```<code>cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES NONE)

###
# Hacky language extension override

function(add_cuda_extensions variable access value current_list_file stack)
  if (NOT cu IN_LIST value)
    list(PREPEND "${variable}" "cu" "CU")
    set("${variable}" "${${variable}}" PARENT_SCOPE)
  endif ()
endfunction()

# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT THRUST_DEVICE_SYSTEM STREQUAL "OMP")
  enable_language(CUDA)
  enable_language(CXX)
else()
  variable_watch(CMAKE_CXX_SOURCE_FILE_EXTENSIONS add_cuda_extensions)
  enable_language(CXX)
endif()

###
# Normal project code starts here

message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")

find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)

add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels PRIVATE Thrust)
</code>```

This waits for the platform module to try to write CMAKE_CXX_SOURCE_FILE_EXTENSIONS and then any time it's accessed, quickly inserts the cu and CU extensions to the list.

Body:
Thrust allows for one to specify different backends at cmake configure time via the THRUST_DEVICE_SYSTEM flag.  My problem is that I have a bunch of .cu files that I want to be compiled as regular c++ files when a user runs cmake with -DTHRUST_DEVICE_SYSTEM=OMP (for example).  If I change the extension of the .cu files to .cpp they compile fine (indicating that I just need tell cmake to use the c++ compiler on the .cu files). But if I add .cu to CMAKE_CXX_SOURCE_FILE_EXTENSIONS then I get a CMake Error: Cannot determine link language for target "cuda_kernels".  Here's a minimal cmake example:

cmake_minimum_required(VERSION 3.19)

project(kernels LANGUAGES C CXX Fortran)

set(KERNELS_USE_OMP OFF)
if ("${THRUST_DEVICE_SYSTEM}" STREQUAL "OMP")
  set(KERNELS_USE_OMP ON)
endif()

# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT KERNELS_USE_OMP)
  enable_language(CUDA)
else()
  list(PREPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS "cu;CU")
endif()

message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")

find_package(Thrust REQUIRED CONFIG)
thrust_create_target(Thrust FROM_OPTIONS)

add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels Thrust)

The output of the message command on my system is: -- cu;CU;C;M;c++;cc;cpp;cxx;mm;mpp;CPP;ixx;cppm

Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?

Body:
Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?

The extension-to-language for <LANG> is set as soon as <LANG> is enabled by inspecting the value of the CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS variable when the language detection module exits.

Unfortunately, there is no blessed way to override this list for CXX as it is hard-coded in Modules/CMakeCXXCompiler.cmake.in.

Perhaps the best way of working around the actual error would be to use the LANGUAGE source file property to tell CMake how to compile the individual CUDA files, like so:

cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES CXX)

find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)

thrust_is_cuda_system_found(USE_CUDA)
if (USE_CUDA)
  enable_language(CUDA)
endif()

set(cuda_kernel_sources my_kernels.cu)

add_library(cuda_kernels ${cuda_kernel_sources})
target_link_libraries(cuda_kernels PRIVATE Thrust)

if (NOT USE_CUDA)
  set_source_files_properties(
    ${cuda_kernel_sources}
    PROPERTIES
    LANGUAGE CXX
  )
endif ()

This will certainly be friendlier to other projects that might try to add_subdirectory yours.

However, if we want to be very naughty, we can do this:

cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES NONE)

###
# Hacky language extension override

function(add_cuda_extensions variable access value current_list_file stack)
  if (NOT cu IN_LIST value)
    list(PREPEND "${variable}" "cu" "CU")
    set("${variable}" "${${variable}}" PARENT_SCOPE)
  endif ()
endfunction()

# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT THRUST_DEVICE_SYSTEM STREQUAL "OMP")
  enable_language(CUDA)
  enable_language(CXX)
else()
  variable_watch(CMAKE_CXX_SOURCE_FILE_EXTENSIONS add_cuda_extensions)
  enable_language(CXX)
endif()

###
# Normal project code starts here

message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")

find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)

add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels PRIVATE Thrust)

This waits for the platform module to try to write CMAKE_CXX_SOURCE_FILE_EXTENSIONS and then any time it's accessed, quickly inserts the cu and CU extensions to the list.


问:
Cypress: parent package runs its cypress/integration test and its dependencies cypress/integration tests
Question: Can a parent Cypress npm project import/add/run the Cypress tests of its dependencies Cypress npm projects?

The response from the question is this link works, breaking up a monolith Cypress test package into multiple Cypress test package and using Module API. However, I have had to rethink my question. What I did not address was that there are dependencies (custom commands) between npm cypress packages.

Cypress: Import tests into "./cypress/integration" from multiple npm dependencies?

Example:

npm package cy_test_A has dependency on npm package cy_test_B custom commands,

npm package cy_test_B has dependency on npm package cy_test_C custom commands.

Each of these packages has cypress integration for specs and src for custom commands:

cy_test_***

```<code>├── cypress
│   ├── integration
│   │   └── tests
│   └── support
│       └── specs
├── src
│   └── commands
</code>```

Can Cypress integration tests be imported from its dependency? When I perform a test run, I want to see a combined tests including both the dependencies' cypress tests + the parent's cypress test.

npm package cy_test_A is dependent on custom commands within npm package cy_test_B, which are used in cy_test_A cypress integration tests. When building npm package cy_test_B, it has its own cypress integration tests before committing to npm repository. I want cy_test_A to run its own cypress integration tests but cypress integration tests of its dependency cy_test_B as well.

```<code>├── cypress
│   ├── integration
│   │   └── tests_A <<< Dependent on src/commands **cy_test_B**
│   │   └── tests_B <<< Imported cypress/integration/tests from **cy_test_B**
│   └── support
│       └── specs
├── src
│   └── commands
├── node_module
│   └── **cy_test_B**
│       └── ***
│       └── ***
</code>```

Ideas? Thank you

答:
Not sure if all t's are crossed, but an index file can be used to collate all the custom commands without physically moving them.

/cypress/support/commands-index.js

require('../../cy_test_A/src/commands')
require('../../cy_test_B/src/commands')
```
<p>Then specify the <code>supportFile</code> to be that index file.</p>
<pre class="lang-js prettyprint-override"><code>const cypress = require('cypress')

cypress.open({
  reporter: 'junit',
  browser: 'chrome',
  project: '..',
  config: {
    supportFile: './cypress-run-other-project/support/commands-index.js',
    video: true,
  },
  env: {
    login_url: '/login',
    products_url: '/products',
  },
})
</code>```

But now, whatever else is going on in /cy_test_A/cypress/support/index.js is ignored (for example add-on libraries), so maybe the commands-index.js needs to be

require('../../cy_test_A/cypress/support')
require('../../cy_test_B/cypress/support')
```
<p>You can check what commands have been loaded with this (in the spec)</p>
<pre class="lang-js prettyprint-override"><code>it('checks that both custom commands have bee loaded', () => {
  const commands = Cypress.Commands._commands
  expect(commands).to.have.property('checkA')  // command from cy_test_A
  expect(commands).to.have.property('checkB')  // command from cy_test_B
})
</code>```

Body:
Question: Can a parent Cypress npm project import/add/run the Cypress tests of its dependencies Cypress npm projects?

The response from the question is this link works, breaking up a monolith Cypress test package into multiple Cypress test package and using Module API. However, I have had to rethink my question. What I did not address was that there are dependencies (custom commands) between npm cypress packages.

Cypress: Import tests into "./cypress/integration" from multiple npm dependencies?

Example:

npm package cy_test_A has dependency on npm package cy_test_B custom commands,

npm package cy_test_B has dependency on npm package cy_test_C custom commands.

Each of these packages has cypress integration for specs and src for custom commands:

cy_test_***

├── cypress
│   ├── integration
│   │   └── tests
│   └── support
│       └── specs
├── src
│   └── commands

Can Cypress integration tests be imported from its dependency? When I perform a test run, I want to see a combined tests including both the dependencies' cypress tests + the parent's cypress test.

npm package cy_test_A is dependent on custom commands within npm package cy_test_B, which are used in cy_test_A cypress integration tests. When building npm package cy_test_B, it has its own cypress integration tests before committing to npm repository. I want cy_test_A to run its own cypress integration tests but cypress integration tests of its dependency cy_test_B as well.

├── cypress
│   ├── integration
│   │   └── tests_A <<< Dependent on src/commands **cy_test_B**
│   │   └── tests_B <<< Imported cypress/integration/tests from **cy_test_B**
│   └── support
│       └── specs
├── src
│   └── commands
├── node_module
│   └── **cy_test_B**
│       └── ***
│       └── ***

Ideas? Thank you

Body:
Not sure if all t's are crossed, but an index file can be used to collate all the custom commands without physically moving them.

/cypress/support/commands-index.js

require('../../cy_test_A/src/commands')
require('../../cy_test_B/src/commands')

Then specify the supportFile to be that index file.

const cypress = require('cypress')

cypress.open({
  reporter: 'junit',
  browser: 'chrome',
  project: '..',
  config: {
    supportFile: './cypress-run-other-project/support/commands-index.js',
    video: true,
  },
  env: {
    login_url: '/login',
    products_url: '/products',
  },
})

But now, whatever else is going on in /cy_test_A/cypress/support/index.js is ignored (for example add-on libraries), so maybe the commands-index.js needs to be

require('../../cy_test_A/cypress/support')
require('../../cy_test_B/cypress/support')

You can check what commands have been loaded with this (in the spec)

it('checks that both custom commands have bee loaded', () => {
  const commands = Cypress.Commands._commands
  expect(commands).to.have.property('checkA')  // command from cy_test_A
  expect(commands).to.have.property('checkB')  // command from cy_test_B
})


问:
How to calculate an equation using eval-parse in R?
How do I calculate the value of an equation using eval parse in R? The value for each component of the equation should be taken from the eponymously named columns within the same row e.g. 'alpha' from column 'alpha' and so on.

Dataframe:

```<code>dput(<alpha beta    gamma   delta   epsilon zeta    eta theta   RF  min.speed.kph   max.speed.kph   speed   equation
9.70E-05    0.0026  1.432   0   0   0   0   0   0   10  130 30  ((alpha*speed^2)+(beta*speed)+gamma+(delta*log10(speed))+(epsilon*exp(zeta*speed))+(eta*(speed^theta)))*(1-RF)
7.40E-05    0.013   1.484   0   0   0   0   0   0   10  130 30  ((alpha*speed^2)+(beta*speed)+gamma+(delta*log10(speed))+(epsilon*exp(zeta*speed))+(eta*(speed^theta)))*(1-RF)
0.000266    -0.014  2.427   0   0   0   0   0   0   10  130 30  ((alpha*speed^2)+(beta*speed)+gamma+(delta*log10(speed))+(epsilon*exp(zeta*speed))+(eta*(speed^theta)))*(1-RF)
2.88E-12    2.56E-10    -2.09E-07   7.75E-05    -0.005274381    0.152658622 0   0.88    NA  10  140 30  ((alpha*speed^5)+beta*speed^4+gamma*speed^3+delta*speed^2+epsilon*speed+zeta)*(theta)
2.88E-12    2.56E-10    -2.09E-07   7.75E-05    -0.005274381    0.152658622 0   0.6 NA  10  140 30  ((alpha*speed^5)+beta*speed^4+gamma*speed^3+delta*speed^2+epsilon*speed+zeta)*(theta)
0.524738843 0   -0.01   0   9.36E-05    0   0   0   0   5   130 30  ((alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2))*(1-RF)
0.283553945 -0.0234 -0.00869    0.000443    0.000114    0   0   0   0   5   130 30  ((alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2))*(1-RF)
0.189162424 1.571506423 0.081547506 0.027327758 -0.000248892    -0.268467236    0   0   0   5   130 30  (alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2)
0.474232144 5.621746462 0.340577763 0.083762882 -0.001515827    -1.191086695    0   0   0   5   130 30  (alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2)
0.189162424 1.571506423 0.081547506 0.027327758 -0.000248892    -0.268467236    0   0   0   5   130 30  (alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2)
>)
</code>```

I have tried this but it's not working:

nox.file$calculated_col <- eval(parse(text=as.character(nox.file$equation)), nox.file)

I have also tried wrapping it in 'mutate' to help with vectorising it but neither does this work:

nox.file <- nox.file %>% mutate(calculated_col=eval(parse(text=as.character(equation)), nox.file))

Can anyone tell me what's wrong?

答:
You could also do:</p>
```<code>df %>%
   rowwise() %>%
   mutate(sol = eval(parse(text = equation)))
</code>```

Body:
How do I calculate the value of an equation using eval parse in R? The value for each component of the equation should be taken from the eponymously named columns within the same row e.g. 'alpha' from column 'alpha' and so on.

Dataframe:

dput(<alpha beta    gamma   delta   epsilon zeta    eta theta   RF  min.speed.kph   max.speed.kph   speed   equation
9.70E-05    0.0026  1.432   0   0   0   0   0   0   10  130 30  ((alpha*speed^2)+(beta*speed)+gamma+(delta*log10(speed))+(epsilon*exp(zeta*speed))+(eta*(speed^theta)))*(1-RF)
7.40E-05    0.013   1.484   0   0   0   0   0   0   10  130 30  ((alpha*speed^2)+(beta*speed)+gamma+(delta*log10(speed))+(epsilon*exp(zeta*speed))+(eta*(speed^theta)))*(1-RF)
0.000266    -0.014  2.427   0   0   0   0   0   0   10  130 30  ((alpha*speed^2)+(beta*speed)+gamma+(delta*log10(speed))+(epsilon*exp(zeta*speed))+(eta*(speed^theta)))*(1-RF)
2.88E-12    2.56E-10    -2.09E-07   7.75E-05    -0.005274381    0.152658622 0   0.88    NA  10  140 30  ((alpha*speed^5)+beta*speed^4+gamma*speed^3+delta*speed^2+epsilon*speed+zeta)*(theta)
2.88E-12    2.56E-10    -2.09E-07   7.75E-05    -0.005274381    0.152658622 0   0.6 NA  10  140 30  ((alpha*speed^5)+beta*speed^4+gamma*speed^3+delta*speed^2+epsilon*speed+zeta)*(theta)
0.524738843 0   -0.01   0   9.36E-05    0   0   0   0   5   130 30  ((alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2))*(1-RF)
0.283553945 -0.0234 -0.00869    0.000443    0.000114    0   0   0   0   5   130 30  ((alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2))*(1-RF)
0.189162424 1.571506423 0.081547506 0.027327758 -0.000248892    -0.268467236    0   0   0   5   130 30  (alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2)
0.474232144 5.621746462 0.340577763 0.083762882 -0.001515827    -1.191086695    0   0   0   5   130 30  (alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2)
0.189162424 1.571506423 0.081547506 0.027327758 -0.000248892    -0.268467236    0   0   0   5   130 30  (alpha+gamma*speed+epsilon*speed^2+zeta/speed)/(1+beta*speed+delta*speed^2)
>)

I have tried this but it's not working:

nox.file$calculated_col <- eval(parse(text=as.character(nox.file$equation)), nox.file)

I have also tried wrapping it in 'mutate' to help with vectorising it but neither does this work:

nox.file <- nox.file %>% mutate(calculated_col=eval(parse(text=as.character(equation)), nox.file))

Can anyone tell me what's wrong?

Body:
You could also do:

df %>%
   rowwise() %>%
   mutate(sol = eval(parse(text = equation)))


问:
How to create a custom Uniform Fan Out Shape in Akka through the Java library
So I am building an Akka custom component to learn the framework. I need to create a UnifromFanOut shape custom component. So I tried to extend the shape but the issue is how do I create the shape with 1 input and 3 outputs. The class requires a seq object which is a part of Scala but I am a bit confused on whether the whole shape itself is correct. I just started learning Akka so I can understand if my approach is wrong. Also I the purpose of the exercise was to create a custom component and I know I can get the logic done through GraphDSL but it needs to be a custom component. My question is how do I create this shape correctly. (the documentation isn't the best for custom components)</p>
```<code>    public final Inlet<DeviceInfo> in = Inlet.create("Map.in");
    public final Outlet<DeviceInfo> temp_out = Outlet.create("Map.out");
    public final Outlet<DeviceInfo> humidity_out = Outlet.create("Map.out");
    public final Outlet<DeviceInfo> illumination_out = Outlet.create("Map.out");
    //Does not work
    private final UniformFanOutShape<DeviceInfo, DeviceInfo> shape = UniformFanOutShape.apply(in, Arrays.asList(temp_out, humidity_out));

    @Override
    public UniformFanOutShape<DeviceInfo, DeviceInfo> shape() {
        return shape;
    }
</code>```

答:
[EDIT]
TL;DR
You basically need to work around calling Scala vararg method from Java. You can do it like this using  scala.collection.mutable.ArrayBuffer

```<code>    ArrayBuffer<Outlet<DeviceInfo>> arrayBuffer = new ArrayBuffer<>();
    arrayBuffer.append(temp_out);
    arrayBuffer.append(humidity_out);
    arrayBuffer.append(illumination_out);

    final UniformFanOutShape<DeviceInfo, DeviceInfo> shape =
      UniformFanOutShape.apply(in, arrayBuffer.toSeq());
</code>```

source: How to use Scala varargs from Java code

[/EDIT]

(the documentation isn't the best for custom components)

I disagree. The documentation is pretty comprehensive (https://doc.akka.io/docs/akka/current/stream/stream-customize.html)

You shouldn't extend UniformFanOutShape<DeviceInfo, DeviceInfo>, but rather GraphStage<UniformFanOutShape<DeviceInfo, DeviceInfo>>.

You then need to override two methods:

```<code> public UniformFanOutShape<DeviceInfo, DeviceInfo> shape() {
    //implement
 }

 @Override
 public GraphStageLogic createLogic(Attributes inheritedAttributes) {
   //implement
 }
</code>```

the documentation shows you how to create shapes and how to implement GraphStageLogic with detailed information about handling backpressure, etc.

The documentation shows examples for SourceShape, SinkShape and FlowShape. If you understand those examples, but need some more guidance you can look at the source code. In akka.stream.scaladsl.Graph.scala you can find implementation of all built in GraphStages Akka Streams provide. For example Broadcast is an example of a UniformFanOutShape stage and this is how the code for it starts:

final class Broadcast[T](val outputPorts: Int, val eagerCancel: Boolean) extends GraphStage[UniformFanOutShape[T, T]]

The implementation is under 100 lines of code and follows the same pattern like the documentation shows. The code is Scala, because Akka is implemented in that language with a thin Java layer meant to be used from Java code. So for example there's also akka.stream.javadsl.Graph.scala, but you will see that the code there is delegating to implementations in scaladsl package. You will see that pattern all over Akka code. So in short you will need to understand a bit of scala to understand the implementation but in this case here it's very similar to what Java implementation could look like.

Body:
So I am building an Akka custom component to learn the framework. I need to create a UnifromFanOut shape custom component. So I tried to extend the shape but the issue is how do I create the shape with 1 input and 3 outputs. The class requires a seq object which is a part of Scala but I am a bit confused on whether the whole shape itself is correct. I just started learning Akka so I can understand if my approach is wrong. Also I the purpose of the exercise was to create a custom component and I know I can get the logic done through GraphDSL but it needs to be a custom component. My question is how do I create this shape correctly. (the documentation isn't the best for custom components)

    public final Inlet<DeviceInfo> in = Inlet.create("Map.in");
    public final Outlet<DeviceInfo> temp_out = Outlet.create("Map.out");
    public final Outlet<DeviceInfo> humidity_out = Outlet.create("Map.out");
    public final Outlet<DeviceInfo> illumination_out = Outlet.create("Map.out");
    //Does not work
    private final UniformFanOutShape<DeviceInfo, DeviceInfo> shape = UniformFanOutShape.apply(in, Arrays.asList(temp_out, humidity_out));

    @Override
    public UniformFanOutShape<DeviceInfo, DeviceInfo> shape() {
        return shape;
    }

Body:
[EDIT]
TL;DR
You basically need to work around calling Scala vararg method from Java. You can do it like this using  scala.collection.mutable.ArrayBuffer

    ArrayBuffer<Outlet<DeviceInfo>> arrayBuffer = new ArrayBuffer<>();
    arrayBuffer.append(temp_out);
    arrayBuffer.append(humidity_out);
    arrayBuffer.append(illumination_out);

    final UniformFanOutShape<DeviceInfo, DeviceInfo> shape =
      UniformFanOutShape.apply(in, arrayBuffer.toSeq());

source: How to use Scala varargs from Java code

[/EDIT]

(the documentation isn't the best for custom components)

I disagree. The documentation is pretty comprehensive (https://doc.akka.io/docs/akka/current/stream/stream-customize.html)

You shouldn't extend UniformFanOutShape<DeviceInfo, DeviceInfo>, but rather GraphStage<UniformFanOutShape<DeviceInfo, DeviceInfo>>.

You then need to override two methods:

 public UniformFanOutShape<DeviceInfo, DeviceInfo> shape() {
    //implement
 }

 @Override
 public GraphStageLogic createLogic(Attributes inheritedAttributes) {
   //implement
 }

the documentation shows you how to create shapes and how to implement GraphStageLogic with detailed information about handling backpressure, etc.

The documentation shows examples for SourceShape, SinkShape and FlowShape. If you understand those examples, but need some more guidance you can look at the source code. In akka.stream.scaladsl.Graph.scala you can find implementation of all built in GraphStages Akka Streams provide. For example Broadcast is an example of a UniformFanOutShape stage and this is how the code for it starts:

final class Broadcast[T](val outputPorts: Int, val eagerCancel: Boolean) extends GraphStage[UniformFanOutShape[T, T]]

The implementation is under 100 lines of code and follows the same pattern like the documentation shows. The code is Scala, because Akka is implemented in that language with a thin Java layer meant to be used from Java code. So for example there's also akka.stream.javadsl.Graph.scala, but you will see that the code there is delegating to implementations in scaladsl package. You will see that pattern all over Akka code. So in short you will need to understand a bit of scala to understand the implementation but in this case here it's very similar to what Java implementation could look like.


问:
KeyError: u'xl/worksheets/Sheet1.xml' is given when try to open xlsx file with python xlrd
I can not process some files using python xlrd library.
This is my code,

```<code>>>> from xlrd import open_workbook, XLRDError
>>> try:
...     book = open_workbook('17112015Rpt1000000178_Report.xlsx')
... except XLRDError as e:
...     print e
...
</code>```

I get the following error.

```<code>     Traceback (most recent call last):
          File "<stdin>", line 2, in <module>
          File "/usr/local/lib/python2.7/dist-packages/xlrd/__init__.py", line 422, in open_workbook
            ragged_rows=ragged_rows,
          File "/usr/local/lib/python2.7/dist-packages/xlrd/xlsx.py", line 790, in open_workbook_2007_xml
            zflo = zf.open(component_names[fname])
KeyError: u'xl/worksheets/Sheet1.xml'
</code>```

How to fix this issue?

答:
I got the same Error Message
You may consider upgrade your xlrd Package.

First upgrade your pip (to avoid problems)
Then upgrade xlrd

usage:

```<code>  python -m pip install --upgrade pip
  pip install xlrd -U
</code>```

It worked for me...
Good luck!!

ContentLicense: CC BY-SA 3.0

Body:
I can not process some files using python xlrd library.
This is my code,

>>> from xlrd import open_workbook, XLRDError
>>> try:
...     book = open_workbook('17112015Rpt1000000178_Report.xlsx')
... except XLRDError as e:
...     print e
...

I get the following error.

     Traceback (most recent call last):
          File "<stdin>", line 2, in <module>
          File "/usr/local/lib/python2.7/dist-packages/xlrd/__init__.py", line 422, in open_workbook
            ragged_rows=ragged_rows,
          File "/usr/local/lib/python2.7/dist-packages/xlrd/xlsx.py", line 790, in open_workbook_2007_xml
            zflo = zf.open(component_names[fname])
KeyError: u'xl/worksheets/Sheet1.xml'

How to fix this issue?

Body:
I got the same Error Message
You may consider upgrade your xlrd Package.

First upgrade your pip (to avoid problems)
Then upgrade xlrd

usage:

  python -m pip install --upgrade pip
  pip install xlrd -U

It worked for me...
Good luck!!


问:
Writing a function that returns true if given string has exactly 6 characters
I am trying to write a function that returns true or false if a given string has exactly  6 consecutive characters with the same value. If the string has more or less than 6, it will return false:

I am not allowed to use lists, sets or import any packages. I am only restricted to while loops, for loops, and utilizing basic mathematical operations

Two example runs are shown below:

```<code>Enter a string: 367777776
True
</code>```
```<code>Enter a string: 3677777777776
False
</code>```

Note that although I entered numbers, it is actually a string within the function argument for example: consecutive('3777776')

I tried to convert the string into an ASCII table and then try and filter out the numbers there. However, I

```<code>def consecutive(x):
    storage= ' '
    acc=0
    count=0
    for s in x:
        storage+= str(ord(s)) + ' '
        acc+=ord(s)
        if acc == acc:
            count+=1
    for s in x-1:

    return count

</code>```

My intention is to compare the previous character's ASCII code  to the current character's ASCII code in the string. If the ASCII doesnt match, I will add an accumulator for it. The accumulator will list the number of duplicates. From there, I will implement an if-else statement to see if it is greater or less than 6 However, I have a hard time translating my thoughts into python code.

Can anyone assist me?

答:
You should store the current sequence of repeated chars.

```<code>def consecutive(x):
    sequencechar = ' '
    repetitions = 0
    for ch in x:
        if ch != sequencechar:
            if repetitions == 6:
                break
            sequencechar = ch
            repetitions = 1
        else:
            repetitions += 1
    return repetitions == 6
</code>```

If I could, I would not have given the entire solution, but this still is a simple problem. However one has to take care of some points.

As you see the current sequence is stored, and when the sequence is ended and a new starts, on having found a correct sequence it breaks out of the for loop.

Also after the for loop ends normally, the last sequence is checked (which was not done in the loop).

Body:
I am trying to write a function that returns true or false if a given string has exactly  6 consecutive characters with the same value. If the string has more or less than 6, it will return false:

I am not allowed to use lists, sets or import any packages. I am only restricted to while loops, for loops, and utilizing basic mathematical operations

Two example runs are shown below:

Enter a string: 367777776
True

Enter a string: 3677777777776
False

Note that although I entered numbers, it is actually a string within the function argument for example: consecutive('3777776')

I tried to convert the string into an ASCII table and then try and filter out the numbers there. However, I

def consecutive(x):
    storage= ' '
    acc=0
    count=0
    for s in x:
        storage+= str(ord(s)) + ' '
        acc+=ord(s)
        if acc == acc:
            count+=1
    for s in x-1:

    return count

My intention is to compare the previous character's ASCII code  to the current character's ASCII code in the string. If the ASCII doesnt match, I will add an accumulator for it. The accumulator will list the number of duplicates. From there, I will implement an if-else statement to see if it is greater or less than 6 However, I have a hard time translating my thoughts into python code.

Can anyone assist me?

Body:
You should store the current sequence of repeated chars.

def consecutive(x):
    sequencechar = ' '
    repetitions = 0
    for ch in x:
        if ch != sequencechar:
            if repetitions == 6:
                break
            sequencechar = ch
            repetitions = 1
        else:
            repetitions += 1
    return repetitions == 6

If I could, I would not have given the entire solution, but this still is a simple problem. However one has to take care of some points.

As you see the current sequence is stored, and when the sequence is ended and a new starts, on having found a correct sequence it breaks out of the for loop.

Also after the for loop ends normally, the last sequence is checked (which was not done in the loop).


问:
Reflector not injected to my custom guard in nestjs
I have created a guard in a separate module for checking feature flags as below

```<code>@Injectable()
export class FeatureFlagGuard implements CanActivate {
    constructor(
        private reflector: Reflector,
        private featureFlagService: FeatureFlagService
    ) {}

    async canActivate(context: ExecutionContext): Promise<boolean> {
        const featureKey = this.reflector.get<string>(
            FEATURE_FLAG_DECORATOR_KEY,
            context.getHandler()
        );

        if (!featureKey) {
            return true;
        }
        return await this.featureFlagService.isFeatureEnabled(featureKey);
    }
}
</code>```

and here is my decorator

```<code>import { SetMetadata } from '@nestjs/common';

export const FEATURE_FLAG_DECORATOR_KEY = 'FEATURE_FLAG';
export const FeatureEnabled = (featureName: string) =>
    SetMetadata(FEATURE_FLAG_DECORATOR_KEY, featureName);
</code>```

Then in appModule I provided the FeatureFlagGuard as below

```<code>    providers: [
        {
            provide: APP_GUARD,
            useClass: FeatureFlagGuard
        }
    ]
</code>```

Then in my controller

```<code>    @FeatureEnabled('FEATURE1')
    @Get('/check-feature-flag')
    checkFeatureFlag() {
        return {
            date: new Date().toISOString()
        };
    }
</code>```

When I run the code I get this error, since the reflector is injected as null into my service

```<code>[error] [ExceptionsHandler] Cannot read properties of undefined (reading 'get')
</code>```

Not sure what I missed

答:
Thanks to @jayMcDoniel to give me a clue

The issue was the FeatureFlagService was not exported from the module. When I exported it the issue is resolved

Body:
I have created a guard in a separate module for checking feature flags as below

@Injectable()
export class FeatureFlagGuard implements CanActivate {
    constructor(
        private reflector: Reflector,
        private featureFlagService: FeatureFlagService
    ) {}

    async canActivate(context: ExecutionContext): Promise<boolean> {
        const featureKey = this.reflector.get<string>(
            FEATURE_FLAG_DECORATOR_KEY,
            context.getHandler()
        );

        if (!featureKey) {
            return true;
        }
        return await this.featureFlagService.isFeatureEnabled(featureKey);
    }
}

and here is my decorator

import { SetMetadata } from '@nestjs/common';

export const FEATURE_FLAG_DECORATOR_KEY = 'FEATURE_FLAG';
export const FeatureEnabled = (featureName: string) =>
    SetMetadata(FEATURE_FLAG_DECORATOR_KEY, featureName);

Then in appModule I provided the FeatureFlagGuard as below

    providers: [
        {
            provide: APP_GUARD,
            useClass: FeatureFlagGuard
        }
    ]

Then in my controller

    @FeatureEnabled('FEATURE1')
    @Get('/check-feature-flag')
    checkFeatureFlag() {
        return {
            date: new Date().toISOString()
        };
    }

When I run the code I get this error, since the reflector is injected as null into my service

[error] [ExceptionsHandler] Cannot read properties of undefined (reading 'get')

Not sure what I missed