Category: Blog

  • iptv_playlist_browser

    iptv_playlist_browser

    This tool allows to browse IPTV playlist in Windows.

    This tool does not provide any stream, you have to use your own.
    Please remember to use only legal streams.

    Run

    python iptv_playlist_browser_gui.py
    

    or

    python -m iptv_playlist_browser
    

    or try the experimental binary.

    In your first run, go to Preferences... menu and set a path for your desired video player.

    Usage

    Main window

    after load

    1. Menu bar

    Get quick access to the main features of the application (open Xtream Code, open playlist, preferences, …).

    2. Filter

    When you have a lot of groups / categories / channels, you can filter them using this text areas.

    3. Groups

    List of groups. Groups come from the values in Xtream API (if available), from the playlist (if available).
    If the groups do not exist, the application will create them artificially according to the parameters.

    Select a group to view it’s categories.

    4. Categories

    List of categories. The application will create them artificially according to the parameters.

    Select a category to view it’s channels.

    5. Channels

    List of channels. Select a channel to view it’s URL. Double-click on a channel to open it with your player.

    6. Watch

    You can see the URL of the selected channel. Click the Watch button to open it with your player.

    7. Catch up

    Some stream may have a catch up replay available. If so, check the Catch up chckbox, select a date, a time and duration and click the Watch button.
    You can find the current EPG in the combo box to easily choose your desired program.

    Preferences

    preferences

    Video player

    Give a path to your favorite video player executable.
    Eg. : C:/Program Files (x86)/VideoLAN/VLC/vlc.exe

    Additional parameters

    (optional) You can provide additional parameters to use with your player.

    Eg. : --fullscreen will launch VLC in fullscreen.

    Remember latest input

    When checked, by default the program will remember your playlist local or remote path, and your Xtream code credentials.

    Always try to retreive Xtream Code

    When checked, if you load a playlist the program will first give a try to the Xtream Code API.
    Xtream Code API allows to have better group naming and to play catch up streams.

    Group / category separator

    Very often the channels in the playlist are separated by false channels to mark the boundary.
    Whith this parameter, you can specify what are the strings used as separator.

    Eg. : if your playlist is like

    #EXTM3U
    #EXTINF:-1,< CHAINES FRANCAISES SD >
    http://myserver.com:8000/login/password/1
    #EXTINF:-1,--- TNT SD ---
    http://myserver.com:8000/login/password/2
    #EXTINF:-1,TF1 SD
    http://myserver.com:8000/login/password/3
    #EXTINF:-1,TF1 +1 SD
    http://myserver.com:8000/login/password/4
    #EXTINF:-1,FRANCE 2 SD
    http://myserver.com:8000/login/password/5
    #EXTINF:-1,FRANCE 3 SD
    http://myserver.com:8000/login/password/6
    

    and you set

    <
    

    as group separator and

    --
    

    as category separator, all lines containing < will be considered as “group” and all lines containing -- will be considered as “category”.
    You’ll obtain:

    after load

    Load playlist from Xtream Code

    Give your Xtream Code credentials.

    Load playlist from local file

    Open a local playlist file (m3u).
    A preview of the names inside the file allows you to guess what separators should be used.

    Load playlist from remote file

    Open a remote playlist file (m3u).

    Eg.: http://myserver.com:8000/get.php?username=login&password=password&type=m3u&output=mpegts

    Filtrer lists

    Type part of desired group, category or channel you want to filter.

    Watch a stream

    Double-click on an entry in the channel list, or select it then click on the Watch button.

    Replay a past stream

    If you opened your playlist with Xtream Code and your provider gives this functionality, you can select a time and date for a specific channel. A list gives you the latest EPG availble to help you.

    Note that not all providers gives this functionality.

    How to install

    Prerequisite

    Install

    Clone repository

    git clone https://github.com/PhunkyBob/iptv_playlist_browser.git
    cd iptv_playlist_browser
    

    Create virtual environment

    With Poetry (recommended) or pip.

    poetry shell
    poetry install
    

    or

    python -m venv venv
    venv\Scripts\activate.bat
    python -m pip install -U pip
    pip install -e .
    

    Compilation

    To create Python files from Qt .ui files:

    pyside6-uic ui\generate_playlist.ui -o iptv_playlist_browser\generate_playlist_pyside6.py
    pyside6-uic ui\local_file.ui -o iptv_playlist_browser\local_file_pyside6.py
    pyside6-uic ui\main_ui.ui -o iptv_playlist_browser\main_ui_pyside6.py
    pyside6-uic ui\preferences.ui -o iptv_playlist_browser\preferences_pyside6.py
    pyside6-uic ui\remote_file.ui -o iptv_playlist_browser\remote_file_pyside6.py
    pyside6-uic ui\xtream_code.ui -o iptv_playlist_browser\xtream_code_pyside6.py
    

    To create Windows .exefile:

    pyinstaller --noconfirm --onefile --windowed --icon "resources\play-button.ico" --paths "iptv_playlist_browser" "iptv_playlist_browser_gui.py"
    
    Visit original content creator repository https://github.com/PhunkyBob/iptv_playlist_browser
  • iptv_playlist_browser

    iptv_playlist_browser

    This tool allows to browse IPTV playlist in Windows.

    This tool does not provide any stream, you have to use your own.
    Please remember to use only legal streams.

    Run

    python iptv_playlist_browser_gui.py
    

    or

    python -m iptv_playlist_browser
    

    or try the experimental binary.

    In your first run, go to Preferences... menu and set a path for your desired video player.

    Usage

    Main window

    after load

    1. Menu bar

    Get quick access to the main features of the application (open Xtream Code, open playlist, preferences, …).

    2. Filter

    When you have a lot of groups / categories / channels, you can filter them using this text areas.

    3. Groups

    List of groups. Groups come from the values in Xtream API (if available), from the playlist (if available).
    If the groups do not exist, the application will create them artificially according to the parameters.

    Select a group to view it’s categories.

    4. Categories

    List of categories. The application will create them artificially according to the parameters.

    Select a category to view it’s channels.

    5. Channels

    List of channels. Select a channel to view it’s URL. Double-click on a channel to open it with your player.

    6. Watch

    You can see the URL of the selected channel. Click the Watch button to open it with your player.

    7. Catch up

    Some stream may have a catch up replay available. If so, check the Catch up chckbox, select a date, a time and duration and click the Watch button.
    You can find the current EPG in the combo box to easily choose your desired program.

    Preferences

    preferences

    Video player

    Give a path to your favorite video player executable.
    Eg. : C:/Program Files (x86)/VideoLAN/VLC/vlc.exe

    Additional parameters

    (optional) You can provide additional parameters to use with your player.

    Eg. : --fullscreen will launch VLC in fullscreen.

    Remember latest input

    When checked, by default the program will remember your playlist local or remote path, and your Xtream code credentials.

    Always try to retreive Xtream Code

    When checked, if you load a playlist the program will first give a try to the Xtream Code API.
    Xtream Code API allows to have better group naming and to play catch up streams.

    Group / category separator

    Very often the channels in the playlist are separated by false channels to mark the boundary.
    Whith this parameter, you can specify what are the strings used as separator.

    Eg. : if your playlist is like

    #EXTM3U
    #EXTINF:-1,< CHAINES FRANCAISES SD >
    http://myserver.com:8000/login/password/1
    #EXTINF:-1,--- TNT SD ---
    http://myserver.com:8000/login/password/2
    #EXTINF:-1,TF1 SD
    http://myserver.com:8000/login/password/3
    #EXTINF:-1,TF1 +1 SD
    http://myserver.com:8000/login/password/4
    #EXTINF:-1,FRANCE 2 SD
    http://myserver.com:8000/login/password/5
    #EXTINF:-1,FRANCE 3 SD
    http://myserver.com:8000/login/password/6
    

    and you set

    <
    

    as group separator and

    --
    

    as category separator, all lines containing < will be considered as “group” and all lines containing -- will be considered as “category”.
    You’ll obtain:

    after load

    Load playlist from Xtream Code

    Give your Xtream Code credentials.

    Load playlist from local file

    Open a local playlist file (m3u).
    A preview of the names inside the file allows you to guess what separators should be used.

    Load playlist from remote file

    Open a remote playlist file (m3u).

    Eg.: http://myserver.com:8000/get.php?username=login&password=password&type=m3u&output=mpegts

    Filtrer lists

    Type part of desired group, category or channel you want to filter.

    Watch a stream

    Double-click on an entry in the channel list, or select it then click on the Watch button.

    Replay a past stream

    If you opened your playlist with Xtream Code and your provider gives this functionality, you can select a time and date for a specific channel. A list gives you the latest EPG availble to help you.

    Note that not all providers gives this functionality.

    How to install

    Prerequisite

    Install

    Clone repository

    git clone https://github.com/PhunkyBob/iptv_playlist_browser.git
    cd iptv_playlist_browser
    

    Create virtual environment

    With Poetry (recommended) or pip.

    poetry shell
    poetry install
    

    or

    python -m venv venv
    venv\Scripts\activate.bat
    python -m pip install -U pip
    pip install -e .
    

    Compilation

    To create Python files from Qt .ui files:

    pyside6-uic ui\generate_playlist.ui -o iptv_playlist_browser\generate_playlist_pyside6.py
    pyside6-uic ui\local_file.ui -o iptv_playlist_browser\local_file_pyside6.py
    pyside6-uic ui\main_ui.ui -o iptv_playlist_browser\main_ui_pyside6.py
    pyside6-uic ui\preferences.ui -o iptv_playlist_browser\preferences_pyside6.py
    pyside6-uic ui\remote_file.ui -o iptv_playlist_browser\remote_file_pyside6.py
    pyside6-uic ui\xtream_code.ui -o iptv_playlist_browser\xtream_code_pyside6.py
    

    To create Windows .exefile:

    pyinstaller --noconfirm --onefile --windowed --icon "resources\play-button.ico" --paths "iptv_playlist_browser" "iptv_playlist_browser_gui.py"
    
    Visit original content creator repository https://github.com/PhunkyBob/iptv_playlist_browser
  • trakt-year-in-review

    Year in Review using Trakt

    Generate year in review from Trakt history

    Requirements

    Python 3.12+

    Generate Trakt Client ID

    If you donot have Trakt client id, You will need to generate it from Trakt.

    1. Login to your account in trakt.tv (Trakt)
    2. Click on your profile (avatar) showing in corner
    3. Click on Settings
    4. Click on “Your API Apps”
    5. provide the details and submit the request.
    6. You will receive client id and client secret. It may take sometime to receive the API keys depending on time taken by Trakt to verify your information.

    Steps

    1. Install required python modules
    pip install -r requirements.txt
    1. Make your Trakt profile as public from Trakt’s account setting (Make it private again after generating year in review)

    2. Create .env file from .env.example file

    cp .env.example .env
    1. Update trakt user name, trakt client id and year in .env file

    2. Run below command on full terminal screen

    python generate.py
    1. Alternatively, You can also pass trakt user name, year and client id in command line argument
    python generate.py user_id 2024 trakt_client_id
    1. Make your Trakt profile as private again from Trakt’s account setting.

    Screenshots

    Visit original content creator repository https://github.com/navilg/trakt-year-in-review
  • trakt-year-in-review

    Year in Review using Trakt

    Generate year in review from Trakt history

    Requirements

    Python 3.12+

    Generate Trakt Client ID

    If you donot have Trakt client id, You will need to generate it from Trakt.

    1. Login to your account in trakt.tv (Trakt)
    2. Click on your profile (avatar) showing in corner
    3. Click on Settings
    4. Click on “Your API Apps”
    5. provide the details and submit the request.
    6. You will receive client id and client secret. It may take sometime to receive the API keys depending on time taken by Trakt to verify your information.

    Steps

    1. Install required python modules
    pip install -r requirements.txt
    1. Make your Trakt profile as public from Trakt’s account setting (Make it private again after generating year in review)

    2. Create .env file from .env.example file

    cp .env.example .env
    1. Update trakt user name, trakt client id and year in .env file

    2. Run below command on full terminal screen

    python generate.py
    1. Alternatively, You can also pass trakt user name, year and client id in command line argument
    python generate.py user_id 2024 trakt_client_id
    1. Make your Trakt profile as private again from Trakt’s account setting.

    Screenshots

    Visit original content creator repository https://github.com/navilg/trakt-year-in-review
  • AcuCallTest

    Prerequisites

    • Visual Studio 2017 version 15.7
    • .NET Core
    • Microsoft SQL Server (Not required on local machine if database is hosted on a server)

    Steps To Run Project

    1. Clone project.
    2. First of all make sure if you want to rename database name then update Database connection settings in appSettings.json -> ConnectionStrings -> AcuCallContext.
    3. You can create database, tables and stored procs using migration or script.
    4. If you want to run Db script then skip from step 5 to 8. Then navigate to Sql\DbScript.sql and execute it.
    5. Migration can be performed by opening Package Manager console and On top right selecting AcuCall.Infrastructure.Data from Default Project.
    6. Then run command Update-Database, It will create database if it does not exist else perform migrations.
    7. Once Migration is performed successfully, We need to enable Broker for Db notifications. So open your SQL Server instance.
    8. Connect to your server instance, and execute ALTER DATABASE [DatabaseName] SET ENABLE_BROKER.
    9. Executing migration or script will create a user admin with password admin.
    10. Now you are all ready to start application.

    Deployment Of Project

    The very first step is to install .NET Core Runtime on your machine.

    Setup IIS Configuration

    Windows Server Operating Systems

    Enable the Web Server (IIS) server role and establish role services

    1. Use the Add Roles and Features wizard from the Manage menu or the link in Server Manager. On the Server Roles step, check the box for Web Server (IIS).
    2. After the Features step, the Role services step loads for Web Server (IIS). Select the IIS role services desired or accept the default role services provided.
    3. You can select different security levels from Web Server > Security if required.
    4. Proceed through the Confirmation step to install the web server role and services. A server/IIS restart isn’t required after installing the Web Server (IIS) role.
    Windows Desktop Operating Systems

    Enable the IIS Management Console and World Wide Web Services

    1. Navigate to Control Panel > Programs > Programs and Features > Turn Windows features on or off (left side of the screen).
    2. Open the Internet Information Services node. Open the Web Management Tools node.
    3. Check the box for IIS Management Console.
    4. Check the box for World Wide Web Services.
    5. Accept the default features for World Wide Web Services.
    6. You can select different security levels from World Wide Web Services > Security if required.

    If the IIS installation requires a restart, restart the system.

    Now Create IIS Site

    1. On the hosting system, create a folder to contain the app’s published folders and files.

    2. Within the new folder, create a logs folder to hold ASP.NET Core Module stdout logs when stdout logging is enabled. If logs folder already exist then we don’t need to create it. This folder will hold error logs happening in website.

    3. Open IIS Manager and then open the server’s node in the Connections panel. Right-click the Sites folder. Select Add Website from the contextual menu. capture

    4. Provide a Site name and set the Physical path to the app’s deployment folder. Provide the Binding configuration by default port is 80 and create the website by selecting OK. capture1

    5. Under the server’s node, select Application Pools.

    6. Right-click the site’s app pool and select Basic Settings from the contextual menu.

    7. In the Edit Application Pool window, set the .NET CLR version to No Managed Code. As ASP.NET Core runs in a separate process and manages the runtime. ASP.NET Core doesn’t rely on loading the desktop CLR. Setting the .NET CLR version to No Managed Code is optional. capture2

    Deploy App

    Deploy the app to the folder created on the hosting system by following below steps.

    1. Right-click the project AcuCall.Web and select Publish.
    2. When Folder is selected, specify a folder path to store the published assets. The default folder is bin\Release\PublishOutput but we need to set the path of Physical Path while creating new website in IIS Manager. Click the Publish button to finish. capture

    NOW your application is served on localhost:[BindingPort]

    For more further information regarding deployment you can visit Microsoft website.

    Configure IIS To Access Website Using IP Address

    1. Open IIS Manager Console, It can be found in Administrative Tools -> Internet Information Services (IIS) Manager.

    2. In the Connections pane of IIS, expand the Sites and select the website AcuCallAspNetCore this is what i have named previously in this doc or the one you have named.

    3. Click on Bindings link and you will see current bindings of that website. capture

    4. Click on Add button.

    5. On the Add Site Binding window, keep website Type as http. Select an IP address from the drop-down menu upon which you want to bind the website. Since other websites (along with their Host Header Values) are already bound on port 80, you won’t be able to bind this new website on port 80 without Host Header Value (Host name). So, specify a port number (other than default port 80) on which you want to bind this new website. Keep Host name as blank, click OK and then Close. Once the binding is added in IIS Manager, the next step is allowing a port in Windows Firewall. capture2

    6. Go to Administrative Tools -> Windows Defender Firewall with Advanced Security.

    7. At Windows Firewall window, click on Inbound Rules. capture

    8. Under Actions pane, click on New Rule and New Inbound Rule Wizard will be opened. On this window, select the Port radio button and click on Next. capture

    9. On the next screen, select TCP and Specific local ports radio button. Specify a port number (upon which you set binding in IIS) in Specific local ports field and click Next. capture

    10. On the next screen, select Allow the connection and click Next. capture

    11. Select the profiles for those we want to apply this rule and click Next. capture

    12. Very last step is to provide Name and Description for the newly created rule & click Finish. capture

    Now we are able to access your website using via IP address like http://VPS-IP-Address:81

    Visit original content creator repository https://github.com/SalmanZahid/AcuCallTest
  • zig-htn-demo

    Hierarchical Task Network (HTN) AI Demo

    This is a demo of a Hierarchical Task Network (HTN) AI implementation in Zig. The only dependency is SDL2.

    The AI has searching and flanking behavior.

    My goals with this project were:

    • To learn Zig.
    • To learn about HTNs.
    • To have as much fun as possible.

    The project has a couple of features that I think are neat:

    Video demos (clickable images)

    Check out the core AI behaviors in the videos below (click on an image to open a youtube video).

    Flanking behavior

    When navigating to the player, the AI will try to flank the player. This behavior is implemented using A* routing with a distance metric biased away from the player’s line of sight.

    The visibility bias is intuitively very simple: consider visible locations further away by a constant factor. This approach works fairly well to avoid moving into player view when near the player while smoothly transitioning to normal movement far away from the player.

    When the AI spots the player, it records a snapshot of the player’s view, finds a nearby hiding place, and then routes to the player using A* with respect to the snapshot of the player’s view.

    Searching behavior

    The AI will default to searching for the player when

    1. The player hasn’t been spotted yet.
    2. The AI has lost track of the player.

    More details on the second case: when the AI spots the player, it will hide and then navigate to the last known player location for an attack. This can fail when the player has moved behind cover while out of the enemy’s line of sight. This is what is meant by losing track of the player.

    Running the demo

    NOTE: this project has only been tested on macOS Monetery 12.4 with an M1 chip. While other platforms / architectures have not been tested, any changes to build.zig should be minimal.

    INSTALLATION

    You need to install the following dependencies before building:

    • SDL2
    • SDL2_Image

    On macOS, you can install these via brew install sdl2 sdl2_image.

    Then,

    • git clone https://github.com/j-helland/zig-htn-demo.git
    • cd zig-htn-demo
    • zig build run

    This should launch the program automatically.

    CONTROLS

    • Move using WASD
    • Quit using Esc
    • Right-click to spawn a wall at the mouse position.
    • Spacebar to spawn an enemy at the mouse position.
    • Use the mouse to control the line-of-sight.

    Project Organization

    • src/game.zig contains the core game loop and GameState definition. Additionally:
      • ECS systems are defined here e.g. handlePlayer
      • The HTN planner is defined here as an ECS system handleEnemyAI.
    • src/ai.zig Defined the HTN domain, as well as the conditions, operators, and sensors needed by the HTN planner to run the AI.
    • src/htn/ Contains the HTN planner, domain builder, and world state definition. Currently, the world state is specialized to this demo, meaning that this HTN implementation requires a small amount of work to be used in other projects.
    • src/ecs/ecs.zig Contains a generic ECS implementation. It is not currently optimized.
    Visit original content creator repository https://github.com/j-helland/zig-htn-demo
  • py-image-storage

    py-image-storage

    What is this?

    This is an application, which keep your image files to be small file sized. I build this application for my home-made server (ODROID N2+, Ubuntu 22.04).

    How it works?

    This application is using ‘Pillow’ library to compress image files. It will compress image files in the source path and save them to the destination path. If the destination path is not exist, it will create it automatically. The original file will be deleted.

    It keeps observing the source path, if there is a new image file, it will compress it and save it to the destination path while it is running.

    Why did you build this?

    Google Photos no longer provide unlimited storage for free, and I was bored.


    How to use.

    0. Prerequisites

    • python3.11
    • pip3
    • virtualenv

    You need to install more libraries, which are in the ‘requirements.txt’ file, after you create virtual environment and activate it.

    1. Install python3.11, pip3 and virtualenv (if you don’t have them)

    sudo apt-get -y install python3.11 python3-pip virtualenv
    # you probably use yum or something else. you would know.

    2. Clone this repository and create virtual environment

    git clone https://github.com/pjc1991/py-image-storage.git
    cd py-image-storage
    /usr/bin/python3.11 -m venv venv
    source venv/bin/activate

    3. Install requirements

    pip3 install -r requirements.txt

    4. Create ‘.env’ file and edit it

    touch .env && vi .env

    # .env
    UNCOMPRESSED=\\NAS\FILES\uncompressed # uncompressed image files path, source path
    COMPRESSED=\\NAS\FILES\compressed # compressed image files path, destination path

    5. Run application

    nohup python -u observer.py &
    tail -f nohup.out
    
    # or you just
    ./start.sh
    # it gives you tail =f nohup.out
    # to stop watching log : CTRL+C

    How to stop application

    ps -ef | grep observer.py
    kill -9 <pid>
    
    # or you just
    ./stop.sh

    I want to watch some logs

    tail -f nohup.out
    
    # or you just
    ./watch_logs.sh

    More Things to do ~

    • Implement async I/O
    • Better performance and structures for async I/O
    • Make a script for stopping application
    • Make this application as a service (systemd)
    • Make a script for installation (not sure if it is necessary

    Tested environment

    I tested this application on Ubuntu 22.04 (Odroid N2+) & Windows 11(My gaming desktop).
    Well, It was fast as the file transfer speed of my server, at least.

    Visit original content creator repository
    https://github.com/pjc1991/py-image-storage

  • laravel-date-scopes

    Laravel Date Scopes

    Latest Version on Packagist Tests License Total Downloads Imports

    This package provides a big range of useful date scopes for your Laravel Eloquent models!

    Let’s assume you have a Transaction model. If you now give it the DateScopes trait, you can do something like this:

    use LaracraftTech\LaravelDateScopes\DateScopes;
    
    class Transaction extends Model
    {
        use DateScopes;
    }
    
    // query transactions created today
    Transaction::ofToday();
     // query transactions created during the last week
    Transaction::ofLastWeek();
     // query transactions created during the start of the current month till now
    Transaction::monthToDate();
     // query transactions created during the last year, start from 2020
    Transaction::ofLastYear(startFrom: '2020-01-01');
    
    // ... and much more scopes are available (see below)
    
    // For sure, you can chain any Builder function you want here.
    // Such as these aggregations, for instance:
    Transaction::ofToday()->sum('amount');
    Transaction::ofLastWeek()->avg('amount');

    ToC

    Installation

    You can install the package via composer:

    composer require laracraft-tech/laravel-date-scopes

    Configuration

    Inclusive/Exclusive

    In statistics, when asking for “the last 7 days”, the current day may or may not be included in the calculation depending on the context and the specific requirements of the analysis.

    If you want to include the current day in the calculation, you would generally use an inclusive range, meaning that you would include records created on the current day as well as records created in the previous 6 days.

    If you want to exclude the current day in the calculation, you would generally use an exclusive range, meaning that you would include records created in the previous 7 days, but not records created on the current day.

    Ultimately, it depends on the context and what you’re trying to achieve with your data. It’s always a good idea to clarify the requirements and expectations with stakeholders to ensure that you’re including or excluding the correct records.

    The same concept applies to other time intervals like weeks, months, quarters, and years etc.

    The default for this package is exclusive approach, which means when you for instance query for the last 7 days it will not include the current day! You can change the default if you need in the published config file.

    Global configuration

    You can publish the config file with:

    php artisan vendor:publish --tag="date-scopes-config"

    This is the contents of the published config file:

    return [
        /**
         * If you want to include the current day/week/month/year etc. in the range,
         * you could use the inclusive range here as a default.
         * Note that you can also fluently specify the range for quite every scope we offer
         * directly when using the scope:
         * Transaction::ofLast7Days(customRange: DateRange::INCLUSIVE); (this works for all but the singular "ofLast"-scopes)
         * This will do an inclusive query, even though the global default range here is set to exclusive.
         */
        'default_range' => env('DATE_SCOPES_DEFAULT_RANGE', DateRange::EXCLUSIVE->value),
    
        /**
         * If you use a global custom created_at column name, change it here.
         */
        'created_column' => env('DATE_SCOPES_CREATED_COLUMN', 'created_at'),
    ];

    If you want to change the default range to inclusive set DATE_SCOPES_DEFAULT_RANGE=inclusive in your .env.

    Fluent date range configuration

    As already mentioned above in the default_range config description text, you can also fluently specify the range for quite every scope we offer directly when using the scope:

    // This works for all "ofLast"-scopes, expect the singulars like "ofLastHour",
    // because it would not make sense for those.
    Transaction::ofLast7Days(customRange: DateRange::INCLUSIVE);

    This will do an inclusive query (today-6 days), even though the global default range here was set to exclusive.

    Fluent created_at column configuration

    If you only want to change the created_at field in one of your models and not globally just do:

    use LaracraftTech\LaravelDateScopes\DateScopes;
    
    class Transaction extends Model
    {
        use DateScopes;
        
        public $timestamps = false;
    
        const CREATED_AT = 'custom_created_at';
    }
    // also make sure to omit the default $table->timestamps() function in your migration
    // and use something like this instead: $table->timestamp('custom_created_at')->nullable();

    Custom start date

    If you want data not starting from now, but from another date, you can do this with:

    // query transactions created during 2019-2020
    Transaction::ofLastYear(startFrom: '2020-01-01')

    Custom datetime column

    If you want to use column other than created_at column, you can pass the column name as parameter to the scope:

    Transaction::ofToday(column: 'approved_at')

    Scopes

    Seconds

    // query by SECONDS
    Transaction::ofJustNow(); // query transactions created just now
    Transaction::ofLastSecond(); // query transactions created during the last second
    Transaction::ofLast15Seconds(); // query transactions created during the last 15 seconds
    Transaction::ofLast30Seconds(); // query transactions created during the last 30 seconds
    Transaction::ofLast45Seconds(); // query transactions created during the last 45 seconds
    Transaction::ofLast60Seconds(); // query transactions created during the last 60 seconds
    Transaction::ofLastSeconds(120); // query transactions created during the last N seconds

    Minutes

    // query by MINUTES
    Transaction::ofLastMinute(); // query transactions created during the last minute
    Transaction::ofLast15Minutes(); // query transactions created during the last 15 minutes
    Transaction::ofLast30Minutes(); // query transactions created during the last 30 minutes
    Transaction::ofLast45Minutes(); // query transactions created during the last 45 minutes
    Transaction::ofLast60Minutes(); // query transactions created during the last 60 minutes
    Transaction::ofLastMinutes(120); // query transactions created during the last N minutes

    Hours

    // query by HOURS
    Transaction::ofLastHour(); // query transactions created during the last hour
    Transaction::ofLast6Hours(); // query transactions created during the last 6 hours
    Transaction::ofLast12Hours(); // query transactions created during the last 12 hours
    Transaction::ofLast18Hours(); // query transactions created during the last 18 hours
    Transaction::ofLast24Hours(); // query transactions created during the last 24 hours
    Transaction::ofLastHours(48); // query transactions created during the last N hours

    Days

    // query by DAYS
    Transaction::ofToday(); // query transactions created today
    Transaction::ofYesterday(); // query transactions created yesterday
    Transaction::ofLast7Days(); // query transactions created during the last 7 days
    Transaction::ofLast21Days(); // query transactions created during the last 21 days
    Transaction::ofLast30Days(); // query transactions created during the last 30 days
    Transaction::ofLastDays(60); // query transactions created during the last N days

    Weeks

    // query by WEEKS
    Transaction::ofLastWeek(); // query transactions created during the last week
    Transaction::ofLast2Weeks(); // query transactions created during the last 2 weeks
    Transaction::ofLast3Weeks(); // query transactions created during the last 3 weeks
    Transaction::ofLast4Weeks(); // query transactions created during the last 4 weeks
    Transaction::ofLastWeeks(8); // query transactions created during the last N weeks

    Months

    // query by MONTHS
    Transaction::ofLastMonth(); // query transactions created during the last month
    Transaction::ofLast3Months(); // query transactions created during the last 3 months
    Transaction::ofLast6Months(); // query transactions created during the last 6 months
    Transaction::ofLast9Months(); // query transactions created during the last 9 months
    Transaction::ofLast12Months(); // query transactions created during the last 12 months
    Transaction::ofLastMonths(24); // query transactions created during the last N months

    Quarters

    // query by QUARTERS
    Transaction::ofLastQuarter(); // query transactions created during the last quarter
    Transaction::ofLast2Quarters(); // query transactions created during the last 2 quarters
    Transaction::ofLast3Quarters(); // query transactions created during the last 3 quarters
    Transaction::ofLast4Quarters(); // query transactions created during the last 4 quarters
    Transaction::ofLastQuarters(8); // query transactions created during the last N quarters

    Years

    // query by YEARS
    Transaction::ofLastYear(); // query transactions created during the last year
    Transaction::ofLastYears(2); // query transactions created during the last N years

    Decades

    // query by DECADES
    Transaction::ofLastDecade(); // query transactions created during the last decade
    Transaction::ofLastDecades(2); // query transactions created during the last N decades

    Centuries

    The centuries may return a different range then you maybe would expect. For instance Transaction::ofLastCentury() would apply a range from 1901-01-01 00:00:00 to 2000-12-31 23:59:59. Maybe you would expect a range from: 1900-01-01 00:00:00 to 1999-12-31 23:59:59.

    Checkout Wikipedia for this behavior: https://en.wikipedia.org/wiki/20th_century

    // query by CENTURIES
    Transaction::ofLastCentury(); // query transactions created during the last century
    Transaction::ofLastCenturies(2); // query transactions created during the last N centuries

    Millenniums

    The millenniums may return a different range then you maybe would expect. For instance Transaction::ofLastMillennium() would apply a range from 1001-01-01 00:00:00 to 2000-12-31 23:59:59. Maybe you would expect a range from: 1000-01-01 00:00:00 to 1999-12-31 23:59:59.

    Checkout Wikipedia for this behavior: https://en.wikipedia.org/wiki/2nd_millennium

    // query by MILLENNIUMS
    Transaction::ofLastMillennium(); // query transactions created during the last millennium
    Transaction::ofLastMillenniums(2); // query transactions created during the last N millenniums

    toNow/toDate

    // query by toNow/toDate
    Transaction::secondToNow(); // query transactions created during the start of the current second till now (equivalent of just now)
    Transaction::minuteToNow(); // query transactions created during the start of the current minute till now
    Transaction::hourToNow(); // query transactions created during the start of the current hour till now
    Transaction::dayToNow(); // query transactions created during the start of the current day till now
    Transaction::weekToDate(); // query transactions created during the start of the current week till now
    Transaction::monthToDate(); // query transactions created during the start of the current month till now
    Transaction::quarterToDate(); // query transactions created during the start of the current quarter till now
    Transaction::yearToDate(); // query transactions created during the start of the current year till now
    Transaction::decadeToDate(); // query transactions created during the start of the current decade till now
    Transaction::centuryToDate(); // query transactions created during the start of the current century till now
    Transaction::millenniumToDate(); // query transactions created during the start of the current millennium till now

    Testing

    composer test

    Upgrading

    Please see UPGRADING for details.

    Changelog

    Please see CHANGELOG for more information on what has changed recently.

    Contributing

    Please see CONTRIBUTING for details.

    Security

    Please review our security policy on how to report security vulnerabilities.

    Credits

    License

    The MIT License (MIT). Please see License File for more information.

    Visit original content creator repository https://github.com/laracraft-tech/laravel-date-scopes
  • laravel-date-scopes

    Laravel Date Scopes

    Latest Version on Packagist Tests License Total Downloads Imports

    This package provides a big range of useful date scopes for your Laravel Eloquent models!

    Let’s assume you have a Transaction model. If you now give it the DateScopes trait, you can do something like this:

    use LaracraftTech\LaravelDateScopes\DateScopes;
    
    class Transaction extends Model
    {
        use DateScopes;
    }
    
    // query transactions created today
    Transaction::ofToday();
     // query transactions created during the last week
    Transaction::ofLastWeek();
     // query transactions created during the start of the current month till now
    Transaction::monthToDate();
     // query transactions created during the last year, start from 2020
    Transaction::ofLastYear(startFrom: '2020-01-01');
    
    // ... and much more scopes are available (see below)
    
    // For sure, you can chain any Builder function you want here.
    // Such as these aggregations, for instance:
    Transaction::ofToday()->sum('amount');
    Transaction::ofLastWeek()->avg('amount');

    ToC

    Installation

    You can install the package via composer:

    composer require laracraft-tech/laravel-date-scopes

    Configuration

    Inclusive/Exclusive

    In statistics, when asking for “the last 7 days”, the current day may or may not be included in the calculation depending on the context and the specific requirements of the analysis.

    If you want to include the current day in the calculation, you would generally use an inclusive range, meaning that you would include records created on the current day as well as records created in the previous 6 days.

    If you want to exclude the current day in the calculation, you would generally use an exclusive range, meaning that you would include records created in the previous 7 days, but not records created on the current day.

    Ultimately, it depends on the context and what you’re trying to achieve with your data. It’s always a good idea to clarify the requirements and expectations with stakeholders to ensure that you’re including or excluding the correct records.

    The same concept applies to other time intervals like weeks, months, quarters, and years etc.

    The default for this package is exclusive approach, which means when you for instance query for the last 7 days it will not include the current day! You can change the default if you need in the published config file.

    Global configuration

    You can publish the config file with:

    php artisan vendor:publish --tag="date-scopes-config"

    This is the contents of the published config file:

    return [
        /**
         * If you want to include the current day/week/month/year etc. in the range,
         * you could use the inclusive range here as a default.
         * Note that you can also fluently specify the range for quite every scope we offer
         * directly when using the scope:
         * Transaction::ofLast7Days(customRange: DateRange::INCLUSIVE); (this works for all but the singular "ofLast"-scopes)
         * This will do an inclusive query, even though the global default range here is set to exclusive.
         */
        'default_range' => env('DATE_SCOPES_DEFAULT_RANGE', DateRange::EXCLUSIVE->value),
    
        /**
         * If you use a global custom created_at column name, change it here.
         */
        'created_column' => env('DATE_SCOPES_CREATED_COLUMN', 'created_at'),
    ];

    If you want to change the default range to inclusive set DATE_SCOPES_DEFAULT_RANGE=inclusive in your .env.

    Fluent date range configuration

    As already mentioned above in the default_range config description text, you can also fluently specify the range for quite every scope we offer directly when using the scope:

    // This works for all "ofLast"-scopes, expect the singulars like "ofLastHour",
    // because it would not make sense for those.
    Transaction::ofLast7Days(customRange: DateRange::INCLUSIVE);

    This will do an inclusive query (today-6 days), even though the global default range here was set to exclusive.

    Fluent created_at column configuration

    If you only want to change the created_at field in one of your models and not globally just do:

    use LaracraftTech\LaravelDateScopes\DateScopes;
    
    class Transaction extends Model
    {
        use DateScopes;
        
        public $timestamps = false;
    
        const CREATED_AT = 'custom_created_at';
    }
    // also make sure to omit the default $table->timestamps() function in your migration
    // and use something like this instead: $table->timestamp('custom_created_at')->nullable();

    Custom start date

    If you want data not starting from now, but from another date, you can do this with:

    // query transactions created during 2019-2020
    Transaction::ofLastYear(startFrom: '2020-01-01')

    Custom datetime column

    If you want to use column other than created_at column, you can pass the column name as parameter to the scope:

    Transaction::ofToday(column: 'approved_at')

    Scopes

    Seconds

    // query by SECONDS
    Transaction::ofJustNow(); // query transactions created just now
    Transaction::ofLastSecond(); // query transactions created during the last second
    Transaction::ofLast15Seconds(); // query transactions created during the last 15 seconds
    Transaction::ofLast30Seconds(); // query transactions created during the last 30 seconds
    Transaction::ofLast45Seconds(); // query transactions created during the last 45 seconds
    Transaction::ofLast60Seconds(); // query transactions created during the last 60 seconds
    Transaction::ofLastSeconds(120); // query transactions created during the last N seconds

    Minutes

    // query by MINUTES
    Transaction::ofLastMinute(); // query transactions created during the last minute
    Transaction::ofLast15Minutes(); // query transactions created during the last 15 minutes
    Transaction::ofLast30Minutes(); // query transactions created during the last 30 minutes
    Transaction::ofLast45Minutes(); // query transactions created during the last 45 minutes
    Transaction::ofLast60Minutes(); // query transactions created during the last 60 minutes
    Transaction::ofLastMinutes(120); // query transactions created during the last N minutes

    Hours

    // query by HOURS
    Transaction::ofLastHour(); // query transactions created during the last hour
    Transaction::ofLast6Hours(); // query transactions created during the last 6 hours
    Transaction::ofLast12Hours(); // query transactions created during the last 12 hours
    Transaction::ofLast18Hours(); // query transactions created during the last 18 hours
    Transaction::ofLast24Hours(); // query transactions created during the last 24 hours
    Transaction::ofLastHours(48); // query transactions created during the last N hours

    Days

    // query by DAYS
    Transaction::ofToday(); // query transactions created today
    Transaction::ofYesterday(); // query transactions created yesterday
    Transaction::ofLast7Days(); // query transactions created during the last 7 days
    Transaction::ofLast21Days(); // query transactions created during the last 21 days
    Transaction::ofLast30Days(); // query transactions created during the last 30 days
    Transaction::ofLastDays(60); // query transactions created during the last N days

    Weeks

    // query by WEEKS
    Transaction::ofLastWeek(); // query transactions created during the last week
    Transaction::ofLast2Weeks(); // query transactions created during the last 2 weeks
    Transaction::ofLast3Weeks(); // query transactions created during the last 3 weeks
    Transaction::ofLast4Weeks(); // query transactions created during the last 4 weeks
    Transaction::ofLastWeeks(8); // query transactions created during the last N weeks

    Months

    // query by MONTHS
    Transaction::ofLastMonth(); // query transactions created during the last month
    Transaction::ofLast3Months(); // query transactions created during the last 3 months
    Transaction::ofLast6Months(); // query transactions created during the last 6 months
    Transaction::ofLast9Months(); // query transactions created during the last 9 months
    Transaction::ofLast12Months(); // query transactions created during the last 12 months
    Transaction::ofLastMonths(24); // query transactions created during the last N months

    Quarters

    // query by QUARTERS
    Transaction::ofLastQuarter(); // query transactions created during the last quarter
    Transaction::ofLast2Quarters(); // query transactions created during the last 2 quarters
    Transaction::ofLast3Quarters(); // query transactions created during the last 3 quarters
    Transaction::ofLast4Quarters(); // query transactions created during the last 4 quarters
    Transaction::ofLastQuarters(8); // query transactions created during the last N quarters

    Years

    // query by YEARS
    Transaction::ofLastYear(); // query transactions created during the last year
    Transaction::ofLastYears(2); // query transactions created during the last N years

    Decades

    // query by DECADES
    Transaction::ofLastDecade(); // query transactions created during the last decade
    Transaction::ofLastDecades(2); // query transactions created during the last N decades

    Centuries

    The centuries may return a different range then you maybe would expect. For instance Transaction::ofLastCentury() would apply a range from 1901-01-01 00:00:00 to 2000-12-31 23:59:59. Maybe you would expect a range from: 1900-01-01 00:00:00 to 1999-12-31 23:59:59.

    Checkout Wikipedia for this behavior: https://en.wikipedia.org/wiki/20th_century

    // query by CENTURIES
    Transaction::ofLastCentury(); // query transactions created during the last century
    Transaction::ofLastCenturies(2); // query transactions created during the last N centuries

    Millenniums

    The millenniums may return a different range then you maybe would expect. For instance Transaction::ofLastMillennium() would apply a range from 1001-01-01 00:00:00 to 2000-12-31 23:59:59. Maybe you would expect a range from: 1000-01-01 00:00:00 to 1999-12-31 23:59:59.

    Checkout Wikipedia for this behavior: https://en.wikipedia.org/wiki/2nd_millennium

    // query by MILLENNIUMS
    Transaction::ofLastMillennium(); // query transactions created during the last millennium
    Transaction::ofLastMillenniums(2); // query transactions created during the last N millenniums

    toNow/toDate

    // query by toNow/toDate
    Transaction::secondToNow(); // query transactions created during the start of the current second till now (equivalent of just now)
    Transaction::minuteToNow(); // query transactions created during the start of the current minute till now
    Transaction::hourToNow(); // query transactions created during the start of the current hour till now
    Transaction::dayToNow(); // query transactions created during the start of the current day till now
    Transaction::weekToDate(); // query transactions created during the start of the current week till now
    Transaction::monthToDate(); // query transactions created during the start of the current month till now
    Transaction::quarterToDate(); // query transactions created during the start of the current quarter till now
    Transaction::yearToDate(); // query transactions created during the start of the current year till now
    Transaction::decadeToDate(); // query transactions created during the start of the current decade till now
    Transaction::centuryToDate(); // query transactions created during the start of the current century till now
    Transaction::millenniumToDate(); // query transactions created during the start of the current millennium till now

    Testing

    composer test

    Upgrading

    Please see UPGRADING for details.

    Changelog

    Please see CHANGELOG for more information on what has changed recently.

    Contributing

    Please see CONTRIBUTING for details.

    Security

    Please review our security policy on how to report security vulnerabilities.

    Credits

    License

    The MIT License (MIT). Please see License File for more information.

    Visit original content creator repository https://github.com/laracraft-tech/laravel-date-scopes
  • deep-equality-data-structures

    Deep Equality Javascript Data Structures

    npm version CI Status Badge

    A drop-in replacement for ES native Map and Set with deep equality support for objects.

    Install

    npm install deep-equality-data-structures

    Why?

    ES Map and Set only support referential equality:

    interface MyType {
        a: number;
    }
    const set = new Set<MyType>();
    set.add({ a: 1 });
    set.add({ a: 1 });
    set.size; // 2

    Now, using deep equality:

    import { DeepSet } from 'deep-equality-data-structures';
    
    interface MyType {
        a: number;
    }
    const set = new DeepSet<MyType>();
    set.add({ a: 1 });
    set.add({ a: 1 });
    set.size; // 1

    How?

    This project relies on the object-hash library to normalize object types to unique strings.

    Comparable Interface

    The following supplemental comparisons/methods are included:

    • equals
    • contains
    • union
    • intersection
    • difference
    // COMPARISONS
    const set1 = new DeepSet([{ a: 1 }, { b: 2 }]);
    const set2 = new DeepSet([{ b: 2 }, { a: 1 }]);
    set1.equals(set2); // true
    
    const set3 = new DeepSet([{ a: 1 }]);
    set1.equals(set3); // false
    set1.contains(set3); // true
    
    // SET OPERATIONS (available for maps, too)
    const set3 = new DeepSet([{ a: 1 }, { b: 2 }]);
    const set4 = new DeepSet([{ b: 2 }, { c: 3 }]);
    set3.union(set4); // DeepSet([{ a: 1 }, { b: 2 }, { c: 3 }])
    set3.intersection(set4); // DeepSet([{ b: 2 }])
    set3.difference(set4); // DeepSet([{ a: 1 }])

    Configuration Options

    The default settings should be suitable for most use cases, but behavior can be configured.

    new DeepSet<V>(values?, options?)
    new DeepMap<K,V>(entries?, options?)

    The options argument is a superset of the options defined for object-hash, with the same defaults (exception: the default algoritm is md5). There are also library-specific options.

    Library-specific options:

    • transformer – a custom function that transforms Map keys/Set values prior to hashing. It does not affect the values that are stored.

      type MyType = { val: number; other: number };
      const a: MyType = { val: 1, other: 1 };
      const b: MyType = { val: 1, other: 2 };
      const transformer = (obj: MyType) => ({ val: obj.val });
      
      const set = new DeepSet([a, b]);
      set.size; // 2
      const set = new DeepSet([a, b], { transformer });
      set.size; // 1
      
      [...set.values()]; // [{ val: 1, other: 2 }]
    • mapValueTransformer – a custom function that transforms Map values prior to hashing. This is only relevant to the .equals/.contains operations from the Comparable interface, as well as the Bi-Directional DeepMap. It does not affect the values that are stored.

      type MyType = { val: number; other: number };
      const a: MyType = { val: 1, other: 1 };
      const b: MyType = { val: 1, other: 2 };
      const mapValueTransformer = (obj: MyType) => ({ val: obj.val });
      
      const map1 = new DeepMap([[1, a]]);
      const map2 = new DeepMap([[1, b]]);
      map1.equals(map2); // false
      
      const map1 = new DeepMap([[1, a]], { mapValueTransformer });
      const map2 = new DeepMap([[1, b]], { mapValueTransformer });
      map1.equals(map2); // true
      
      [...map1.entries()]; // [[1, { val: 1, other: 1 }]]
      [...map2.entries()]; // [[1, { val: 1, other: 2 }]]
    • useToJsonTransform – if true, only use JSON-serializable properties when computing hashes, equality, etc. (default: false)

      NOTE: This transform will always be applied BEFORE transformer and mapValueTransformer, if applicable.

      class A {
          constructor(public x: number) {}
      }
      class B {
          constructor(public x: number) {}
      }
      const a = new A(45);
      const b = new B(45);
      
      const set = new DeepSet([a, b]);
      set.size; // 2
      const set = new DeepSet([a, b], { useToJsonTransform: true });
      set.size; // 1
    • caseInsensitive – If true, all string values–including keys/values within objects and arrays–will be evaluated as case-insensitive. (default: false)

      NOTE: This transform will always be applied AFTER transformer and mapValueTransformer, if applicable. For objects, it will be applied before replacer (from object-hash options).

      const a = { key: 'value' };
      const b = { key: 'VALUE' };
      
      const set = new DeepSet([a, b]);
      set.size; // 2
      const set = new DeepSet([a, b], { caseInsensitive: true });
      set.size; // 1

    Bi-Directional DeepMap

    This library also exposes a BiDirectionalDeepMap class, which supports O(1) lookups by both keys and values. It provides the following extended API:

    • hasValue(val: V): boolean: Returns true if val exists as a value in the map
    • getKeyByValue(val: V): K | undefined: Returns the key associated with val if it exists
    • deleteByValue(val: V): boolean: Removes the key-value pair whose value is val and returns true if found

    Caveats

    Note that this “two-way” map has the traditional caveats:

    • There is a ~2x memory footprint
    • Keys and values must be 1-to-1, meaning each key must have a distinct value and vice versa. This implementation will error if attempting to set a key-value pair whose value is already present in the map with a different key.

    Static Utility Methods

    • areEqual(values, options?): Returns true if all elements in values are equal. This can be useful when you need to quickly test equality of more than 2 values, or when you want to specify an equality transform (via options.transformer).

    Notes/Caveats

    • This still supports primitive keys/values like traditional Map/Set.
    • Don’t mutate objects stored in the data structure. The internal representation is not affected by this mutation, so behavior may be unexpected.
    • Don’t mutate objects in the user-supplied transformer or mapValueTransformer functions. It will affect the stored version.
    • This implementation does not explicitly “handle” key collisions. However, with the default algorithm (MD5), even if a map contained one TRILLION entries, the probability of a collision on the next insert is only 0.000000000000001. If you need better odds, use SHA1, SHA256, etc.

    CI/CD

    Using Github Actions, the CI build will run on all pull requests and pushes/merges to main.

    This project uses Conventional Commits and standard-version to facilitate versioning and changelogs.

    Visit original content creator repository https://github.com/adamhamlin/deep-equality-data-structures