Snippets Collections
class Invoice_Events
{

    [PostHandlerFor(classStr(NW_InvoiceDP), methodStr(NW_InvoiceDP, processReport))]
    public static void NW_InvoiceDP_Post_processReport(XppPrePostArgs args)
    {
        SalesTable  SalesTable;
        SalesLine   SalesLine;
        DirPartyPostalAddressView           dirPartyPostalAddrlocal;
        DirPartyLocationRolesView           dirPartyLocationRoleslocal;
        LogisticsLocationRole               logisticsLocRole;
        NW_InvoiceType                      InvoiceType;
        CustInvoiceJour                     InvoiceJour;
        DimensionAttributeValueSetStorage   dimStorage;

        NW_InvoiceDP dpInstance = args.getThis() as NW_InvoiceDP;
        NW_InvoiceTmp InvoiceTmp = dpInstance.getASASSalesInvoiceTmp();
        SalesTable = SalesTable::find(InvoiceTmp.SalesId);
        select InvoiceType where InvoiceType.CodeType == SalesTable.InvoiceType;
        select InvoiceJour where InvoiceJour.InvoiceId == InvoiceTmp.InvoiceId;

        select firstOnly * from dirPartyPostalAddrlocal order by RecId desc
        exists join dirPartyLocationRoleslocal
            where dirPartyLocationRoleslocal.Location   == dirPartyPostalAddrlocal.Location
                && dirPartyLocationRoleslocal.Party     == CustTable::find(SalesTable.CustAccount).Party
                && dirPartyPostalAddrlocal.IsPrimary == NoYes::No
            exists join logisticsLocRole
            where logisticsLocRole.Name     == 'Arabic Add' //like Delivery,Invoice,Business
                && logisticsLocRole.RecId   == dirPartyLocationRoleslocal.LocationRole
                && logisticsLocRole.IsPostalAddress;
        ttsbegin;
        InvoiceTmp.ArAddress = dirPartyPostalAddrlocal.address;
        InvoiceTmp.InvoiceTypeAr = InvoiceType.Arabic;
        InvoiceTmp.InvoiceTypeEn = InvoiceType.English;
        InvoiceTmp.ServiceMonth = strFmt("%1/%2",InvoiceJour.Month,InvoiceJour.Year);
        select firstonly SalesLine where SalesLine.SalesId == SalesTable.SalesId;
        dimStorage = DimensionAttributeValueSetStorage::find(SalesLine.DefaultDimension);
        InvoiceTmp.Project = ProjTable::find(dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName('FD04_Profit_Center').RecId)).Name;
        // CustTable.VATNum
        InvoiceTmp.update();
        ttscommit;
        NW_InvoiceLineTmp InvoiceLineTmp = dpInstance.getASASSalesInvoiceLineTmp();
        ttsbegin;
        while select forUpdate InvoiceLineTmp
        {
            select SalesLine where SalesLine.SalesId == SalesTable.SalesId
                && SalesLine.LineAmount == InvoiceLineTmp.LineAmountMST
                && SalesLine.SalesQty == InvoiceLineTmp.qty;
            InvoiceLineTmp.SalesUnit = SalesLine.SalesUnit;
            InvoiceLineTmp.update();
        }
        ttscommit;
    }

}
DimensionAttributeValueSetStorage dimStorage;

dimStorage = DimensionAttributeValueSetStorage::find(SalesLine.DefaultDimension);
InvoiceTmp.Project = ProjTable::find(dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName('FD04_Profit_Center').RecId)).Name;
        
Online education has transformed the way students access learning opportunities, providing flexibility and accessibility to millions of learners worldwide. However, this shift to digital classrooms has introduced a unique set of challenges for both students and institutions. While online learning offers unmatched convenience, it also requires a high level of self-discipline, organization, and independent work—qualities that many students may struggle to maintain in the absence of traditional classroom structures. To cope with these pressures, more and more students are turning to [url=https://takemyclassonline.net/]pay someone to take my class[/url] services, which offer professional assistance to complete assignments, exams, and even entire courses. This burgeoning industry has raised questions about the ethical implications of outsourcing academic tasks, the potential consequences for student learning, and how it might shape the future of education.
One of the primary reasons for the increasing demand for "Take My Online Class" services is the overwhelming nature of online coursework. While traditional college courses are often accompanied by in-person instruction and scheduled class time, online courses require students to manage their time independently. For many students, particularly those juggling multiple commitments such as part-time jobs, internships, or family responsibilities, keeping up with the pace of coursework can become a daunting task. The flexibility that online education offers—such as being able to study and complete assignments at one’s own pace—can quickly turn into a challenge when students find themselves overwhelmed with deadlines and coursework. In this context, hiring a professional to take over some or all of their coursework can help students stay on track academically, ensuring that they maintain their grades without sacrificing other aspects of their lives.
The types of courses that students take online also contribute to the demand for these services. While some online programs are relatively easy to navigate, others, especially those in fields such as engineering, business, or the sciences, require an advanced level of expertise and understanding. These subjects often involve complex problem-solving, research, and technical skills, which can be difficult for students who are not well-versed in the subject matter. For students in these programs, completing assignments and studying for exams can feel overwhelming. “Take My Online Class” services provide access to experts in various fields, who [url=https://takemyclassonline.net/nurs-fpx-4020-assessment-1-enhancing-quality-and-safety/]nurs fpx 4020 assessment 1[/url] are well-equipped to help students complete their coursework with the depth and accuracy required. By outsourcing these tasks, students can ensure their work meets academic standards without struggling to grasp challenging concepts on their own.
International students also face unique challenges in online education. Many online courses are taught in English, and for students whose first language is not English, this can present significant obstacles. Writing papers, participating in discussions, and understanding complex readings can be much harder for non-native English speakers. In addition, the differences in academic writing styles and cultural expectations between countries can further complicate the learning process. To overcome these challenges, international students often turn to "Take My Online Class" services to help with writing assignments, essays, and other tasks that require fluency in academic English. These services help level the playing field, ensuring that international students are not disadvantaged due to language barriers, and enabling them to submit high-quality work that meets the expectations of their professors.
Another reason for the rising popularity of these services is the sheer volume of coursework that online students are often required to complete. Many online programs require students to engage in frequent assignments, quizzes, and discussions, which can be overwhelming when combined with exams and projects. This constant flow of work can create significant stress for students, especially when they are balancing other life responsibilities. In these cases, outsourcing specific tasks, such as writing papers or taking exams, can give students the breathing room they need to focus on other academic requirements or personal commitments. While these services are not meant to replace the learning process, they can serve as a valuable tool for students who find themselves struggling to keep up with their course load.
Despite the clear advantages of using “Take My Online Class” services, the practice has sparked significant debate regarding academic integrity and the role of technology in education. Critics argue that outsourcing assignments and exams undermines the [url=https://takemyclassonline.net/nurs-fpx-4020-assessment-2-root-cause-analysis-and-safety-improvement-plan/]nurs fpx 4020 assessment 2[/url] educational process by allowing students to bypass the very work that is meant to foster learning and intellectual growth. According to this viewpoint, education is more than just a means of obtaining grades; it is about developing critical thinking, problem-solving, and research skills that will serve students well in their professional lives. By paying someone else to do their work, students may miss out on developing these crucial competencies. Furthermore, there is the potential for students to rely too heavily on these services, leading to a lack of engagement with their coursework and a shallow understanding of the material.
There are also concerns about cheating and plagiarism. While many “Take My Online Class” services promise to provide original work and ensure that assignments meet academic standards, there is always the risk that students could end up submitting work that is plagiarized or not entirely their own. This could lead to serious academic consequences, including failing the course or facing disciplinary action. Moreover, it is difficult to monitor the practices of all services, and some may not adhere to the ethical standards they claim to uphold. These risks have led some critics to argue that these services contribute to the erosion of academic honesty and fairness.
On the other hand, supporters of “Take My Online Class” services argue that these platforms offer valuable academic assistance, similar to tutoring services or study groups. Many students seek help from tutors, professors, or peers to better understand the material and complete their coursework. In this sense, outsourcing certain tasks does not necessarily detract from the learning process, but rather provides students with the additional support they need to succeed. In fact, some argue that these services help students focus on the most challenging aspects of their studies, allowing them to engage more deeply with the material rather [url=https://takemyclassonline.net/nurs-fpx-4020-assessment-3-improvement-plan-in-service-presentation/]nurs fpx 4020 assessment 3[/url] than becoming bogged down by routine assignments. When used responsibly, these services can provide a helpful supplement to the learning process, without undermining the student’s overall education.
Another point to consider is the role of technology in reshaping the way education is delivered and consumed. The growth of “Take My Online Class” services highlights a larger trend toward greater reliance on technology in education. As more students take advantage of online learning opportunities, educational institutions are increasingly adopting digital tools, such as automated grading systems, online tutoring platforms, and interactive learning environments. These technologies are designed to make learning more efficient and accessible, but they also raise questions about the potential for students to use them to bypass the learning process. Some argue that the convenience of outsourcing academic work could eventually lead to a shift in how we value education, where the focus is placed more on grades and outcomes rather than on the actual learning process.
Despite the controversy surrounding “Take My Online Class” services, it is clear that they have filled a gap in the online education system. For students who are overwhelmed by the demands of their coursework, these services provide a valuable resource that can help them maintain their academic standing. They offer a way for students to balance their academic obligations with other aspects of their lives, such as work, family, or personal health. Moreover, these services help bridge the gap for students who may be struggling with difficult material or language barriers, ensuring that they are not left behind due to circumstances beyond their control.
In conclusion, “Take My Online Class” services represent a growing trend in modern education, one that reflects both the opportunities and challenges presented by online learning. While these services provide a valuable solution for students who are struggling to keep up with their coursework, they also raise important ethical and educational questions. As the demand for these services continues to rise, educational institutions may need to explore new ways to support students and help them stay engaged with their studies. Ultimately, the future of online education will likely involve finding a [url=https://takemyclassonline.net/nurs-fpx-4020-assessment-4-improvement-plan-tool-kit/]nurs fpx 4020 assessment 4[/url] balance between flexibility, academic integrity, and the support systems necessary to help students succeed.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ArrowScript : MonoBehaviour
{
    private Rigidbody2D rb;
    private bool hasHit = false;
    private float horizontalInput;

    void Start()
    {
        // گرفتن ریگیدبادی
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // اگر تیر هنوز به چیزی برخورد نکرده، ردیابی زاویه حرکت را انجام بده
        if (!hasHit)
        {
            AlignWithMovement();
        }
    }

    void AlignWithMovement()
    {
        // بررسی جهت حرکت و چرخاندن تیر
        if (rb.velocity.magnitude > 0.1f)
        {
            float angle = Mathf.Atan2(rb.velocity.y, rb.velocity.x) * Mathf.Rad2Deg;
            transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
        }
      
    }

    private void OnCollisionEnter2D(Collision2D col)
    {
        // توقف تیر پس از برخورد
        hasHit = true;
        rb.velocity = Vector2.zero; // توقف حرکت
        rb.isKinematic = true; // غیر فعال کردن فیزیک
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shot : MonoBehaviour
{
    public float LaunchForce = 5f; // قدرت شلیک اولیه
    public float MinLaunchForce = 2f; // حداقل قدرت شلیک
    public float MaxLaunchForce = 20f; // حداکثر قدرت شلیک
    public float ScrollSensitivity = 1f; // حساسیت اسکرول موس
    public GameObject Arrow; // تیر
    public Transform ArrowSpawnPoint; // نقطه شروع تیر (ترانسفرم)


    public GameObject SimpleArrow;
    private GameObject currentArrow;
    void Update()
    {
        // تغییر قدرت شلیک با اسکرول موس
        AdjustLaunchForceWithMouseScroll();



        if (Input.GetKeyDown(KeyCode.Q))
        {
            currentArrow = SimpleArrow;

            Debug.Log("Switched to Simple Arrow");
        }
        // شلیک با دکمه Space
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Shoot();
        }
    }

    void AdjustLaunchForceWithMouseScroll()
    {
        // خواندن مقدار اسکرول موس
        float scroll = Input.GetAxis("Mouse ScrollWheel");

        // تغییر قدرت شلیک بر اساس اسکرول
        LaunchForce += scroll * ScrollSensitivity;

        // محدود کردن قدرت شلیک بین حداقل و حداکثر
        LaunchForce = Mathf.Clamp(LaunchForce, MinLaunchForce, MaxLaunchForce);

        // نمایش مقدار قدرت شلیک در کنسول (اختیاری)
       // Debug.Log("Current Launch Force: " + LaunchForce);
    }

    void Shoot()
    {
        // ایجاد یک نمونه از تیر
        GameObject ArrowIns = Instantiate(Arrow, ArrowSpawnPoint.position, ArrowSpawnPoint.rotation);

        Rigidbody2D rb = ArrowIns.GetComponent<Rigidbody2D>();
        if (rb != null)
        {
            rb.isKinematic = false;
            rb.AddForce(ArrowSpawnPoint.right * LaunchForce, ForceMode2D.Impulse);
        }
    }
}
using UnityEngine;

public class Bow : MonoBehaviour
{
    private Vector2 direction; // جهت چرخش
    private Animator anim; // مرجع انیماتور
    private bool isAttacking = false; // وضعیت حمله
    private Rigidbody2D rb; // مرجع Rigidbody2D
    public float horizontalInput;
    public float moveSpeed = 5f; // سرعت حرکت

    void Start()
    {
        // گرفتن انیماتور و Rigidbody2D از آبجکت
        anim = GetComponent<Animator>();
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // حرکت به چپ و راست
        float horizontalInput = Input.GetAxis("Horizontal");

        // اعمال سرعت به Rigidbody2D
        rb.velocity = new Vector2(horizontalInput * moveSpeed, rb.velocity.y);

        // چرخاندن شخصیت بر اساس جهت حرکت
        if (horizontalInput > 0.01f)
        {
            transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y);
        }
        else if (horizontalInput < -0.01f)
        {
            transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y);
        }

        // فعال کردن انیمیشن دویدن
        anim.SetBool("run", horizontalInput != 0);

        //// وقتی دکمه ماوس فشرده می‌شود
        //if (Input.GetMouseButton(0)) // کلیک چپ نگه داشته شود
        //{
        //    StartAttack();
        //}
        //else // وقتی کلیک رها شود
        //{
        //    StopAttack();
        //}

        //// در صورتی که حمله فعال نباشد، چرخش به سمت ماوس انجام شود
        if (!isAttacking)
        {
            Aim();
        }
    }

    void Aim()
    {
        // محاسبه موقعیت ماوس و کمان
        Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector2 bowPos = transform.position;

        // محاسبه جهت
        direction = mousePos - bowPos;

        // چرخش کمان به سمت ماوس
        transform.right = direction;
    }

    //void StartAttack()
    //{
    //    if (!isAttacking)
    //    {
    //        isAttacking = true;
    //        anim.SetBool("click", true); // انیمیشن Attack
    //    }
    //}

    //void StopAttack()
    //{
    //    if (isAttacking)
    //    {
    //        isAttacking = false;
    //        anim.SetBool("click", false); // بازگشت به انیمیشن Idle
    //    }
    //}
}
import pygame
pygame.init()

win = pygame.display.set_mode((500,480))

pygame.display.set_caption("First Game")

walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
bg = pygame.image.load('bg.jpg')
char = pygame.image.load('standing.png')

clock = pygame.time.Clock()


class player(object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5
        self.isJump = False
        self.left = False
        self.right = False
        self.walkCount = 0
        self.jumpCount = 10
        self.standing = True

    def draw(self, win):
        if self.walkCount + 1 >= 27:
            self.walkCount = 0

        if not(self.standing):
            if self.left:
                win.blit(walkLeft[self.walkCount//3], (self.x,self.y))
                self.walkCount += 1
            elif self.right:
                win.blit(walkRight[self.walkCount//3], (self.x,self.y))
                self.walkCount +=1
        else:
            if self.right:
                win.blit(walkRight[0], (self.x, self.y))
            else:
                win.blit(walkLeft[0], (self.x, self.y))
                


class projectile(object):
    def __init__(self,x,y,radius,color,facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.facing = facing
        self.vel = 8 * facing

    def draw(self,win):
        pygame.draw.circle(win, self.color, (self.x,self.y), self.radius)



def redrawGameWindow():
    win.blit(bg, (0,0))
    man.draw(win)
    for bullet in bullets:
        bullet.draw(win)
    
    pygame.display.update()


#mainloop
man = player(200, 410, 64,64)
bullets = []
run = True
while run:
    clock.tick(27)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        
    for bullet in bullets:
        if bullet.x < 500 and bullet.x > 0:
            bullet.x += bullet.vel
        else:
            bullets.pop(bullets.index(bullet))

    keys = pygame.key.get_pressed()

    if keys[pygame.K_SPACE]:
        if man.left:
            facing = -1
        else:
            facing = 1
            
        if len(bullets) < 5:
            bullets.append(projectile(round(man.x + man.width //2), round(man.y + man.height//2), 6, (0,0,0), facing))

    if keys[pygame.K_LEFT] and man.x > man.vel:
        man.x -= man.vel
        man.left = True
        man.right = False
        man.standing = False
    elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
        man.x += man.vel
        man.right = True
        man.left = False
        man.standing = False
    else:
        man.standing = True
        man.walkCount = 0
        
    if not(man.isJump):
        if keys[pygame.K_UP]:
            man.isJump = True
            man.right = False
            man.left = False
            man.walkCount = 0
    else:
        if man.jumpCount >= -10:
            neg = 1
            if man.jumpCount < 0:
                neg = -1
            man.y -= (man.jumpCount ** 2) * 0.5 * neg
            man.jumpCount -= 1
        else:
            man.isJump = False
            man.jumpCount = 10
            
    redrawGameWindow()

pygame.quit()
// banner 

function banners_post() {
	$labels = array(
		'name'                  => _x( 'Banners', 'Post type general name'),
		'singular_name'         => _x( 'Banner', 'Post type singular name'),
		'menu_name'             => _x( 'Banners', 'Admin Menu text'),
		'name_admin_bar'        => _x( 'Banner', 'Add New on Toolbar'),
		'add_new'               => __( 'Add New'),
		'add_new_item'          => __( 'Add New Banner'),
		'new_item'              => __( 'New Banner'),
		'edit_item'             => __( 'Edit Banner'),
		'view_item'             => __( 'View Banner'),
		'all_items'             => __( 'All Banners'),
		'search_items'          => __( 'Search Banners'),
		'parent_item_colon'     => __( 'Parent Banners:'),
		'not_found'             => __( 'No Banners found.'),
		'not_found_in_trash'    => __( 'No Banners found in Trash.'),
	);

	$args = array(
		'labels'             => $labels,
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'query_var'          => true,
		'rewrite'            => array( 'slug' => 'banner' ),
		'capability_type'    => 'post',
		'has_archive'        => true,
		'hierarchical'       => false,
		'menu_position'      => null,
		'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
	);

	register_post_type( 'banner', $args );
}

add_action( 'init', 'banners_post' );


function banner_loop() {
    $args = array(
        'post_type' => 'banner',
        'posts_per_page' => -1
    );

    $query = new WP_Query( $args );
?>
    <section class="bannerSlider slider">
        <?php
    if ( $query->have_posts() ) {
        
        while ( $query->have_posts() ) {
            $query->the_post();
            ?>
                    
            <div>
                <div class="bannerMain">
                    <div class="bannerContent">
                        <?php the_content(); ?>
<!--                         <h5><//?php the_field('banner_designation'); ?></h5> -->
                    </div>
                    <div class="identity">
						<h2><?php the_title(); ?></h2>
                        <?php the_post_thumbnail('full'); ?>
                    </div>
                </div>
            </div>
                
                
            <?php
        }

        // Reset post data
        wp_reset_postdata();
    }
    ?>
    </section>
    <?php
}
add_shortcode('our-banners','banner_loop');

// banners end



jquery
// Initialize Slick Slider for Banner Slider
jQuery(".bannerSlider").slick({
    slidesToShow: 1,
    slidesToScroll: 1,
    dots: true,
    arrows: false,
    prevArrow: '<button class="slide-arrow prev-arrow"></button>',
    nextArrow: '<button class="slide-arrow next-arrow"></button>',
    autoplay: true,
    autoplaySpeed: 5000,
    pauseOnDotsHover: true,
    adaptiveHeight: true,
});

// Initialize Slick Slider for Lazy Loading
jQuery(".lazy").slick({
    lazyLoad: 'ondemand', // ondemand progressive anticipated
    infinite: true
});

// Add Mouse Wheel Navigation
jQuery('.bannerSlider, .lazy').on('wheel', function (e) {
    e.preventDefault(); // Prevent default scrolling behavior
    if (e.originalEvent.deltaY < 0) {
        // Scroll up
        jQuery(this).slick('slickPrev');
    } else {
        // Scroll down
        jQuery(this).slick('slickNext');
    }
});



csss
.top-head h4.info-box-title {
    font-size: 24px !important;
		    line-height: 44px !important;
}

.top-icon .box-icon-wrapper.box-with-icon {
    margin-top: 34px;
}

.wd-header-nav {
    background: #191919;
		height: 60px;

}

span.nav-link-text {
    color: #fff;
    font-size: 18px;
		padding-top: 20px;
}

.info-img span.wd-btn-text {
    color: #d50404;
}

.info-img-1 .info-box-icon {
    width: 100% !important;
}

/* .info-img-1 img {
    width: 100% !important;
}
 */

.info-img span.wd-btn-text:hover {
    color: #000;
}


.bannerContent a {
    background: #ca0404;
    width: 50%;
    padding: 12px 23px;
    color: #fff;
    font-family: 'Poppins';
    font-weight: 500;
}

.bannerContent a:hover {
    background: #2d2d2d;
}


.info-img .btn.btn-style-link {
    border-bottom: none;
}

.info-img-1 .info-box-content {
    background-color: #fbfbfb;
    top: -15px;
    padding: 20px;
    border: 1px solid #999999;
		height: 176px;
}

.info-img .info-box-content {
    background-color: #fbfbfb;
    top: -15px;
    padding: 20px;
    border: 1px solid #999999;
		height: 176px;
}



.info-img-1 a.btn {
    background-color: #ca0404;
    color: #fff;
}

.btn.btn-color-default:hover {
    color: #fff !important;
}

span.fpara {
    color: #7f7f7f;
}

.copyrights-wrapper.copyrights-two-columns {
    display: none;
}


/* newsletter */
.elementor-field-group.elementor-column.elementor-field-type-submit.elementor-col-20.e-form__buttons {
    display: none;
}
/* newsletter */

/* .bannerContent h2 {
    position: absolute;
    top: 2%;
		left: 50%;
    font-size: 34px;
    color: #fff;
}

.bannerContent p {
    position: absolute;
    top: 12%;
    left: 50%;
    right: 5%;
    color: #fff;
} */

.bannerMain img {
    width: 100%;
}


.bannerContent {
    background: #000000ad !important;
    position: absolute;
    z-index: 999;
    top: 0px;
    bottom: 0px;
    right: 0px;
    margin: auto;
    width: 30%;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 50px;
}

.bannerMain {
    position: relative;
}

.bannerImg {
    position: relative;
    z-index: 0;
}

.bannerContent h2 {
    color: #fff;
    font-size: 30px;
}

.bannerContent p {
    color: #fff;
    font-size: 14px;
}

.bannerSlider {
    position: relative;
}

.bannerSlider ul {
    position: absolute;
    bottom: 0;
    display: flex;
    left: 70%;
    padding: 0;
    margin: 0;
    list-style: none;
    width: 30%;
}

.bannerSlider ul li {
    margin: 0;
    width: 16.6%;
    background: linear-gradient(180deg, #383838, #1b1b1b);
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #1b1b1b;
    border-top: 1px solid #2e2e2e;
    border-bottom: 0;
}

.bannerSlider ul li button {
    background: transparent;
    color: #fff;
    font-size: 18px;
}

.menu li a {
    height: 59px;
    display: flex;
    padding: 0 10px;
    align-items: flex-start;
    position: relative;
    z-index: 1;
}

.menu li {
    height: 59px;
    display: flex;
}

.menu li a:after {
    content: '';
    position: absolute;
    width: 100%;
    height: 0px;
    background: linear-gradient(180deg, #d60404, #940101);
    z-index: -1;
    left: 0;
}

.menu li a:hover:after {
    animation: slide-top 0.2s linear both;
}

.slide-top {
	animation: slide-top 0.5s linear both;
}

@keyframes slide-top {
  0% {
    height: 0;
  }
  100% {
    height: 60px;
  }
}

.wd-prefooter {
    padding: 0px;
}


span.auto-style1 {
    color: #E9322D;
    font-size: 28px;
}

.HVR-CLR a {
    color: #d50404;
		font-weight: 600;
}

.HVR-CLR a:hover {
    color: #000;
    text-decoration: underline;
}


input {
    border-color: #E9322D !important;
    color: #000 !important;
    border-radius: 7px !important;
    padding: 20px 10px !important;
}

textarea#wpforms-364-field_6 {
    border-color: #E9322D !important;
    color: #000 !important;
    border-radius: 7px !important;
}

button#wpforms-submit-364 {
    background-color: #000;
    color: #E9322D;
    border: none;
    border-radius: 6px;
    padding: 13px 40px;
    font-size: 16px;
}

input.s.wd-search-inited {
    border: 1px solid #D7D7D7 !important;
}

button.searchsubmit {
    color: #DE352C !important;
}

input.s {
    border-radius: 0px !important;
    border: none;
}


.chaatRow table th {
    border: 2px dashed #000;
}
.chaatRow table tbody td {
    border: 2px dashed #000;
}

::marker {
    color: #BF2130;
}


h2.head1 {
    text-transform: capitalize;
    margin-left: 22px;
    font-size: 30px;
}

h2.bgClr {
    background-color: #C02130;
    color: #fff;
    padding: 10px 30px;
    margin-left: 27px;
}

.chartRow1 table th {
    border: 2px dashed #000;
}
.chartRow1 table tbody td {
    border: 2px dashed #000;
}

.chartRow1 li {
	border-bottom: 2px dashed   #000;
	padding: 8px;
}

p.flexCon {
    font-size: 12px;
}

p.flexCon1 {
    font-size: 12px;
}

p.flexPrice {
    margin-bottom: 0px;
    margin-top: 36px;
}

.chartRow1 ul {
    margin: 0;
}
.chartRow1 ul li:last-child {
    border: none;
}
p.flexCon {
    padding-left: 50px;
}

.chartData p.flexCon {
    padding-left: 50px;
}
.chartRow1 table tbody .chartData ul li {
    padding-bottom: 0;
}

h3.bgClr {
    background-color: #C02130;
    color: #fff;
    padding: 20px;
    text-align: center;
    font-size: 26px;
}


.chartRow3 li div {
    display: flex;
    justify-content: space-between;
}
.chartRow3 li {
    list-style: none;
    border: none;
    position: relative;
}
.chartRow3 li:after {
    content: '';
    position: absolute;
    height: 1px;
    width: 100%;
    border-top: 2px dashed #000;
    right: 100px;
    top: 0;
    bottom: 0;
    margin: auto;
}
.chartRow3 li div h2 {
    margin: 0;
}

.chartRow3 li:nth-child(1):after {
    width: 69%;
}
.chartRow3 li:nth-child(2):after {
    width: 57%;
}
.chartRow3 li:nth-child(3):after {
    width: 45%;
}
.chartRow3 li:nth-child(4):after {
    width: 24%;
}
.chartRow3 li:nth-child(5):after {
    width: 33%;
}
.chartRow3 li:nth-child(6):after {
    width: 29%;
}
.chartRow3 li:nth-child(7):after {
    width: 30%;
}
.chartRow3 li:nth-child(8):after {
    width: 22%;
}

ul.chartRow3.flexChart li div h2 {
    display: flex;
    flex-direction: column;
}

ul.chartRow3.flexChart li div h2 p {
    font-size: 17px;
}

ul.chartRow3.flexChart li:nth-child(1):after {
    width: 43%;
    top: -20px;
}

ul.chartRow3.flexChart li:nth-child(2):after {
    width: 64%;
    top: -30px;
}

ul.chartRow3.flexChart li:nth-child(3):after {
    top: -10px;
    width: 41%;
}

ul.chartRow3.flexChart li:nth-child(4):after {
    width: 67%;
}

ul.chartRow3.flexChart li:nth-child(5):after {
    width: 47%;
}

ul.chartRow3.flexChart.flexChart1 li:nth-child(1):after {
    width: 67%;
    top: -40px;
}

ul.chartRow3.flexChart.flexChart1 li:nth-child(2):after {
    width: 66%;
    top: -40px;
}

ul.chartRow3.flexChart.flexChart1 li:nth-child(3):after {
    width: 60%;
    top: -42px;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(1):after {
    width: 60%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(2):after {
    width: 60%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(3):after {
    width: 62%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(4):after {
    width: 41%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow3.flexChart.flexChart2 li:nth-child(5):after {
    width: 43%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart li:nth-child(1):after {
    width: 60%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart li:nth-child(2):after {
    width: 58%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart li:nth-child(3):after {
    width: 50%;
    top: 0;
    bottom: 0;
    margin: auto;
}

ul.chartRow5.chartRow3.flexChart.flexChart1 li:nth-child(1):after {
    width: 50%;
}

ul.chartRow5.chartRow3.flexChart.flexChart1 li:nth-child(2):after {
    width: 55%;
}

ul.chartRow5.chartRow3.flexChart.flexChart1 li:nth-child(3):after {
    width: 57%;
    top: 25px;
}




@isTest
    static void testProcessCasesSuccess() {
        List<RecordType> recordTypes2 = [SELECT Id FROM RecordType WHERE SObjectType = 'Case' AND DeveloperName IN ('Reclamacao', 'ProcessoLogistico')];
        List<Case> cases = [SELECT Id, Status, CreatedDate, RecordTypeId FROM Case WHERE RecordTypeId IN :recordTypes2];
        for(Case c : cases) {
            Test.setCreatedDate(c.Id, DateTime.newInstance(2023,12,12));
            c = [SELECT Id, CreatedDate, RecordType.Name, status, StatusDayCount__c FROM Case WHERE Id = :c.Id];
        }
        
        Test.startTest();
        AutoCloseCases.processCases();
        Test.stopTest();
    }
<?php
//Database credentials
$host = 'localhost';
$port = 3306;
$dbName = 'blog';
$username = 'root';
$password = '';

$dsn = "mysql:host={$host};dbname={$dbName};port={$port};charset=utf8";

try {
    // create PDO instance
    $pdo = new PDO($dsn, $username, $password);

//    set PDO to throw exceptions on error
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//    Fetch as associative array
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

} catch (PDOException $e) {
// if error catch
    echo "Connection Failed {$e->getMessage()}";
}
import java.util.*;

public class Main {

    static class Line {
        int x1, y1, x2, y2;

        public Line(int x1, int y1, int x2, int y2) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
        }
    }

    private static int countCells(Line line, Pair<Integer, Integer> star, boolean split) {
        if (line.x1 == line.x2) {
            if (split) {
                return Math.min(Math.abs(star.second - line.y1), Math.abs(star.second - line.y2)) + 1;
            } else {
                return Math.abs(line.y1 - line.y2) + 1;
            }
        } else {
            if (split) {
                return Math.min(Math.abs(star.first - line.x1), Math.abs(star.first - line.x2)) + 1;
            } else {
                return Math.abs(line.x1 - line.x2) + 1;
            }
        }
    }

    private static boolean intersects(Line a, Line b, Pair<Integer, Integer> intersection) {
        if (a.x1 == a.x2 && b.y1 == b.y2) {
            if (b.x1 <= a.x1 && a.x1 <= b.x2 && a.y1 <= b.y1 && b.y1 <= a.y2) {
                intersection.set(a.x1, b.y1);
                return true;
            }
        }
        if (a.y1 == a.y2 && b.x1 == b.x2) {
            if (a.x1 <= b.x1 && b.x1 <= a.x2 && b.y1 <= a.y1 && a.y1 <= b.y2) {
                intersection.set(b.x1, a.y1);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt();
        List<Line> lines = new ArrayList<>();
        for (int i = 0; i < N; ++i) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            if (x1 > x2 || (x1 == x2 && y1 > y2)) {
                int temp = x1;
                x1 = x2;
                x2 = temp;
                temp = y1;
                y1 = y2;
                y2 = temp;
            }
            lines.add(new Line(x1, y1, x2, y2));
        }

        int K = sc.nextInt();
        Map<Pair<Integer, Integer>, List<Line>> stars = new HashMap<>();

        for (int i = 0; i < N; ++i) {
            for (int j = i + 1; j < N; ++j) {
                Pair<Integer, Integer> intersection = new Pair<>(0, 0);
                if (intersects(lines.get(i), lines.get(j), intersection)) {
                    stars.computeIfAbsent(intersection, k -> new ArrayList<>()).add(lines.get(i));
                    stars.computeIfAbsent(intersection, k -> new ArrayList<>()).add(lines.get(j));
                }
            }
        }

        int totalIntensity = 0;
        for (Map.Entry<Pair<Integer, Integer>, List<Line>> entry : stars.entrySet()) {
            if (entry.getValue().size() / 2 == K) {
                List<Integer> intensities = new ArrayList<>();
                for (Line line : entry.getValue()) {
                    intensities.add(countCells(line, entry.getKey(), true));
                }
                totalIntensity += Collections.min(intensities);
            }
        }

        System.out.println(totalIntensity);
    }

    // Pair class to store x and y coordinates of intersections
    static class Pair<T, U> {
        T first;
        U second;

        public Pair(T first, U second) {
            this.first = first;
            this.second = second;
        }

        public void set(T first, U second) {
            this.first = first;
            this.second = second;
        }
    }
}
import java.util.*;

public class Main {
    
    private static int maxRemovals(String currentString, List<String> substrings, Map<String, Integer> memo) {
        if (memo.containsKey(currentString)) {
            return memo.get(currentString);
        }

        int maxCount = 0;

        for (String substring : substrings) {
            int position = currentString.indexOf(substring);
            if (position != -1) {
                String newString = currentString.substring(0, position) + currentString.substring(position + substring.length());
                maxCount = Math.max(maxCount, 1 + maxRemovals(newString, substrings, memo));
            }
        }

        memo.put(currentString, maxCount);
        return maxCount;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int numSubstrings = sc.nextInt();
        List<String> substrings = new ArrayList<>();

        for (int i = 0; i < numSubstrings; i++) {
            substrings.add(sc.next());
        }

        String mainString = sc.next();
        Map<String, Integer> memo = new HashMap<>();

        System.out.println(maxRemovals(mainString, substrings, memo));
    }
}
import java.util.*;

public class Main {
    private static final int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

    private static boolean isValidMove(int x, int y, int gridSize, char[][] grid) {
        return x >= 0 && x < gridSize && y >= 0 && y < gridSize && grid[x][y] != 'M';
    }

    private static int findMinCost(int gridSize, char[][] grid, int[] startPos, int[] endPos) {
        int[][] minCost = new int[gridSize][gridSize];
        for (int i = 0; i < gridSize; i++) {
            Arrays.fill(minCost[i], Integer.MAX_VALUE);
        }

        Queue<int[]> bfsQueue = new LinkedList<>();
        bfsQueue.add(startPos);
        minCost[startPos[0]][startPos[1]] = 0;

        while (!bfsQueue.isEmpty()) {
            int[] currentPos = bfsQueue.poll();
            int x = currentPos[0];
            int y = currentPos[1];

            for (int[] direction : directions) {
                int nextX = x + direction[0];
                int nextY = y + direction[1];

                if (isValidMove(nextX, nextY, gridSize, grid)) {
                    int moveCost = (grid[x][y] == 'T' && grid[nextX][nextY] == 'T') ? 0 : 1;
                    if (minCost[x][y] + moveCost < minCost[nextX][nextY]) {
                        minCost[nextX][nextY] = minCost[x][y] + moveCost;
                        bfsQueue.add(new int[]{nextX, nextY});
                    }
                }
            }
        }

        return minCost[endPos[0]][endPos[1]];
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int gridSize = sc.nextInt();
        char[][] grid = new char[gridSize][gridSize];
        int[] startPos = new int[2];
        int[] endPos = new int[2];

        for (int i = 0; i < gridSize; i++) {
            for (int j = 0; j < gridSize; j++) {
                grid[i][j] = sc.next().charAt(0);
                if (grid[i][j] == 'S') startPos = new int[]{i, j};
                if (grid[i][j] == 'E') endPos = new int[]{i, j};
            }
        }

        int result = findMinCost(gridSize, grid, startPos, endPos);
        System.out.println(result);
    }
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int productCount = sc.nextInt();
        int[] productIds = new int[productCount];
        int[] productCosts = new int[productCount];

        for (int i = 0; i < productCount; i++) {
            productIds[i] = sc.nextInt();
        }
        for (int i = 0; i < productCount; i++) {
            productCosts[i] = sc.nextInt();
        }

        int totalBudget = sc.nextInt();

        int maxFreeItems = 0, maxFreeWorth = 0;

        for (int i = 0; i < productCount; i++) {
            int currentCost = productCosts[i];
            int maxPurchaseQty = totalBudget / currentCost;

            if (maxPurchaseQty > 0) {
                int freeItems = 0;
                int freeWorth = 0;

                for (int j = 0; j < productCount; j++) {
                    if (i != j && productIds[i] % productIds[j] == 0) {
                        freeItems += maxPurchaseQty;
                        freeWorth += productCosts[j] * maxPurchaseQty;
                    }
                }

                if (freeItems > maxFreeItems || 
                   (freeItems == maxFreeItems && freeWorth > maxFreeWorth)) {
                    maxFreeItems = freeItems;
                    maxFreeWorth = freeWorth;
                }
            }
        }

        System.out.println(maxFreeItems + " " + maxFreeWorth);
    }
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int nodes = sc.nextInt();
        int edges = sc.nextInt();
        List<Set<Integer>> adjacencyList = new ArrayList<>();

        for (int i = 0; i < nodes; i++) {
            adjacencyList.add(new HashSet<>());
        }

        for (int i = 0; i < edges; i++) {
            int node1 = sc.nextInt();
            int node2 = sc.nextInt();
            adjacencyList.get(node1).add(node2);
            adjacencyList.get(node2).add(node1);
        }

        int targetActiveNodes = sc.nextInt();
        boolean[] currentActiveNodes = new boolean[nodes];
        Arrays.fill(currentActiveNodes, true);
        int activeNodeCount = nodes;
        int days = 1;

        while (activeNodeCount < targetActiveNodes) {
            boolean[] nextActiveNodes = new boolean[nodes];
            for (int i = 0; i < nodes; i++) {
                int activeNeighbors = 0;
                for (int neighbor : adjacencyList.get(i)) {
                    if (currentActiveNodes[neighbor]) activeNeighbors++;
                }

                if (currentActiveNodes[i] && activeNeighbors == 3) {
                    nextActiveNodes[i] = true;
                } else if (!currentActiveNodes[i] && activeNeighbors < 3) {
                    nextActiveNodes[i] = true;
                }
            }

            currentActiveNodes = nextActiveNodes;
            activeNodeCount = 0;
            for (boolean isActive : currentActiveNodes) {
                if (isActive) activeNodeCount++;
            }
            days++;
        }

        System.out.println(days);
    }
}
git remote add origin https://github.com/Asadullah109/sigma-togather.git
git branch -M main
git push -u origin main
echo "# sigma-togather" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/Asadullah109/sigma-togather.git
git push -u origin main
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String string = br.readLine();
        int length = string.length();
        String[] input = br.readLine().split(" ");
        int[] values = new int[length];

        for (int i = 0; i < length; i++) {
            values[i] = Integer.parseInt(input[i]);
        }

        int res = 0;
        int lastDigit = string.charAt(0) - '0';
        int previousValue = values[0];

        for (int i = 1; i < length; i++) {
            int currentDigit = string.charAt(i) - '0';
            if (currentDigit == lastDigit) {
                res += Math.min(previousValue, values[i]);
                previousValue = Math.max(previousValue, values[i]);
            } else {
                lastDigit = currentDigit;
                previousValue = values[i];
            }
        }

        System.out.println(res);
    }
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String string = sc.next();
        int length = string.length();
        int res = 0;

        int[] values = new int[length];
        for (int i = 0; i < length; i++) {
            values[i] = sc.nextInt();
        }

        int lastDigit = string.charAt(0) - '0';
        int previousValue = values[0];

        for (int i = 1; i < length; i++) {
            int currentDigit = string.charAt(i) - '0';
            if (currentDigit == lastDigit) {
                res += Math.min(previousValue, values[i]);
                previousValue = Math.max(previousValue, values[i]);
            } else {
                lastDigit = currentDigit;
                previousValue = values[i];
            }
        }

        System.out.println(res);
    }
}
int partition(vector<int>& arr, int low, int high) {
  
    // Choose the pivot
    int pivot = arr[high];
    int i = low - 1;

    // Traverse arr[;ow..high] and move all smaller
    
    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    
    // Move pivot after smaller elements and return its posn
    swap(arr[i + 1], arr[high]);  
    return i + 1;
}

void quickSort(vector<int>& arr, int low, int high) {
  
    if (low < high) {
      
        // pi is the partition return index of pivot
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}
		if(head==NULL || k==1){
            return head;
        }
        ListNode* dummy=new ListNode(0);
         dummy->next=head;
        ListNode *cur=dummy,*pre=dummy, *nex=dummy;
       
        int cnt=0;
        while(cur->next!=NULL){
            cur=cur->next;
            cnt++;
        }
        while(cnt>=k){
            cur=pre->next;
            nex= cur->next;
            for(int i=1;i<k;i++){
                cout<<dummy->next->val;
                cur->next=nex->next;
                nex->next=pre->next;
                pre->next=nex;
                nex=cur->next;
                
            }
            pre=cur;
            cnt-=k;
        }
        return dummy->next;
void heapSort(vector<int>& arr){
    int n = arr.size();

    // Build heap (rearrange vector)
    for (int i = n / 2 - 1; i >= 0; i--)
        heapify(arr, n, i);

    // One by one extract an element from heap
    for (int i = n - 1; i > 0; i--) {

        // Move current root to end
        swap(arr[0], arr[i]);

        // Call max heapify on the reduced heap
        heapify(arr, i, 0);
    }
}
void heapify(vector<int>& arr, int n, int i){

    // Initialize largest as root
    int largest = i;

    // left index = 2*i + 1
    int l = 2 * i + 1;

    // right index = 2*i + 2
    int r = 2 * i + 2;

    // If left child is larger than root
    if (l < n && arr[l] > arr[largest])
        largest = l;

    // If right child is larger than largest so far
    if (r < n && arr[r] > arr[largest])
        largest = r;

    // If largest is not root
    if (largest != i) {
        swap(arr[i], arr[largest]);

        // Recursively heapify the affected sub-tree
        heapify(arr, n, largest);
    }
}
#envelope{
margin: 150px;
position: relative;
width: 280px;
height: 180px;
borer-bottom-lefgt-radius:6px;
borer-bottom-lefgt-radius:6px;
margin-left: auto;
margin-left: auto;
top: 150px;
backgorund-color: #f9c5c8
box-shadow: 0 4px 20px rgba(0,0,0,,0.2)
}
for each  account in Account_Certificate[Status == "Draft"]
	{
		if(counter <= 8000)
		{
			accountId = account.ID;
			reciepents = account.Recipient_Emails.toList();
			for each  rec in reciepents
			{
				sendmail
				[
					from :zoho.adminuserid
					to :rec
					subject :"Account Certificate"
					message :"Account Name: " + account.Account_Name
					Attachments :template:Account_Certificate:Account_Certificate accountId as PDF
				]
				counter = counter + 1;
			}
			account.Status="Sent";
		}
	}
	///////// Accounts Emails ///////
	for each  account in Account_Certificate[Status == "Draft"]
	{
		if(counter <= 8000)
		{
			accountId = account.ID;
			reciepents = account.Recipient_Emails.toList();
			for each  rec in reciepents
			{
				sendmail
				[
					from :zoho.adminuserid
					to :rec
					subject :"Account Certificate"
					message :"Account Name: " + account.Account_Name
					Attachments :template:Account_Certificate:Account_Certificate accountId as PDF   ///// template: <record_template2>: <form_link_name2><record_id_variable2> as <attachment_format> //
				]
				counter = counter + 1;
			}
			account.Status="Sent";
		}
	}
import React, { useRef, useState, useEffect } from 'react'
import { HotTable } from '@handsontable/react'
import 'handsontable/dist/handsontable.full.min.css'
import Handsontable from 'handsontable'
import {
  registerControl,
  RegisterControlProps,
  RegisteredControlProperties,
} from '../hoc/registerControl'
import { CustomContentRenderer } from './utils/customButtonRenderer'
import { hyperformulaInstance, sheetId } from './utils/hyperformulaConfig'
import { reformatDate, reformatCurrency } from './utils/formatters'
import { SpreadsheetProperties } from '@components/features/FormBuilder/FormBuilderFieldProperties/Spreadsheet/types'
import { registerAllCellTypes } from 'handsontable/cellTypes'
import { registerAllPlugins } from 'handsontable/plugins'
import { useFormBuilderWorksheetGrid } from '../../hooks/useFormBuilderWorksheetGrid'
import { createSpreadsheetDefaultValue } from '../../FormBuilderFieldProperties/Spreadsheet/constants'
import { useFormBuilder } from '../../hooks/useFormBuilder'
import { useFormService } from '../../hooks/useFormService'

registerAllCellTypes()
registerAllPlugins()

type Properties = RegisteredControlProperties &
  SpreadsheetProperties & {
    externalVariables?: {
      [key: string]: {
        propertyName?: string
        defaultValue?: number
      }
    }
  }

const SpreadsheetControl: React.FC<RegisterControlProps<Properties>> = (
  props
) => {
  const hotTableRef = useRef<any>(null)
  const containerRef = useRef<HTMLDivElement>(null)

  const { rows = 1, columns = 1 } = props.properties || {}

  const DEFAULT_COLUMN_WIDTH = 100
  const DEFAULT_ROW_HEIGHT = 25

  const defaultMeta = {
    data: createSpreadsheetDefaultValue(rows, columns),
    cellFormats: {} as { [key: string]: 'date' | 'currency' | undefined },
    mergeCellsConfig: [],
    formulas: [],
  }

  const meta = props.properties?.meta || defaultMeta
  const { actions: formBuilderWorksheetActions } = useFormBuilderWorksheetGrid()
  const { actions, data: formBuilderData } = useFormBuilder()
  const { watch } = useFormService()
  const formData = watch()

  if (!actions || !actions.getAllFields) {
  }

  const [data, setData] = useState(
    () => props?.value ?? JSON.parse(JSON.stringify(meta.data))
  )
  const [cellFormats, setCellFormats] = useState(meta.cellFormats)
  const [mergeCellsConfig, setMergeCellsConfig] = useState(
    meta.mergeCellsConfig
  )

  const [count, setCount] = useState(0)

  const [formulas, setFormulas] = useState<
    { row: number; col: number; formula: string }[]
  >(meta.formulas || [])

  useEffect(() => {
    if (props.runtime && props.properties?.meta) {
      const {
        data: metaData,
        formulas: metaFormulas = [],

        mergeCellsConfig: metaMergeCells,
      } = props.properties.meta

      setData(props.value ?? metaData)
      setFormulas(metaFormulas)
      setMergeCellsConfig(metaMergeCells)

      metaFormulas.forEach(({ row, col, formula }) => {
        try {
          hyperformulaInstance.setCellContents({ sheet: sheetId, row, col }, [
            [formula],
          ])
        } catch (error) {}
      })

      hyperformulaInstance.rebuildAndRecalculate()
    }
  }, [props.runtime, props.properties?.meta])

  console.log('Meta:', props)

  // useEffect(() => {
  //   if (
  //     !props.externalVariables ||
  //     Object.keys(props.externalVariables).length === 0
  //   ) {
  //     return
  //   }

  //   const existingExpressions = new Set(
  //     hyperformulaInstance.listNamedExpressions()
  //   )

  //   Object.entries(props.externalVariables).forEach(([key, property]) => {
  //     const typedProperty = property as {
  //       propertyName?: string
  //       defaultValue?: number
  //     }
  //     const variableName = typedProperty.propertyName || key
  //     const value = Number(typedProperty.defaultValue || 0)

  //     if (!existingExpressions.has(variableName)) {
  //       try {
  //         hyperformulaInstance.addNamedExpression(variableName, value, sheetId)
  //         existingExpressions.add(variableName)
  //       } catch (error) {
  //         console.error(
  //           `Failed to add named expression: ${variableName}`,
  //           error
  //         )
  //       }
  //     } else {
  //       try {
  //         hyperformulaInstance.changeNamedExpression(
  //           variableName,
  //           value,
  //           sheetId
  //         )
  //       } catch (error) {
  //         console.error(
  //           `Failed to update named expression: ${variableName}`,
  //           error
  //         )
  //       }
  //     }
  //   })

  //   try {
  //     hyperformulaInstance.rebuildAndRecalculate()
  //     syncSpreadsheetWithEngine()
  //   } catch (error) {
  //     console.error('Error recalculating HyperFormula instance:', error)
  //   }
  // }, [props.externalVariables])
  // console.log('External Variable:', props.externalVariables)

  const syncSpreadsheetWithEngine = () => {
    if (hotTableRef.current?.hotInstance && typeof sheetId === 'number') {
      const updatedData = hyperformulaInstance.getSheetValues(sheetId)
      console.log('UpdatedData:', updatedData)
      try {
        hotTableRef.current.hotInstance.loadData(updatedData)
        updateFieldProperties({ data: updatedData })
      } catch (error) {}
    }
  }

  // useEffect(() => {
  //   if (formBuilderData) {
  //     const existingExpressions = hyperformulaInstance.listNamedExpressions()

  //     Object.entries(formBuilderData).forEach(([key, value]) => {
  //       const numericValue = Number(value) || 0

  //       if (!existingExpressions.includes(key)) {
  //         hyperformulaInstance.addNamedExpression(key, numericValue)
  //       } else {
  //         hyperformulaInstance.changeNamedExpression(key, numericValue)
  //       }
  //     })

  //     try {
  //       hyperformulaInstance.rebuildAndRecalculate()

  //       if (sheetId !== undefined) {
  //         const recalculatedData = hyperformulaInstance.getSheetValues(sheetId)
  //         setData(recalculatedData)
  //         updateFieldProperties({ data: recalculatedData })
  //       } else {
  //       }
  //     } catch (error) {}
  //   }
  // }, [formBuilderData])

  // useEffect(() => {
  //   if (formBuilderData?.fields) {
  //     const existingExpressions = new Set(
  //       hyperformulaInstance.listNamedExpressions()
  //     )

  //     formBuilderData.fields.forEach((field) => {
  //       const propertyName = field.properties?.propertyName
  //       const defaultValue = Number(field.properties?.defaultValue || 0)

  //       if (propertyName && !existingExpressions.has(propertyName)) {
  //         try {
  //           hyperformulaInstance.addNamedExpression(propertyName, defaultValue)
  //           existingExpressions.add(propertyName)
  //         } catch (error) {}
  //       } else if (propertyName) {
  //         try {
  //           hyperformulaInstance.changeNamedExpression(
  //             propertyName,
  //             defaultValue
  //           )
  //         } catch (error) {}
  //       }
  //     })

  //     try {
  //       hyperformulaInstance.rebuildAndRecalculate()
  //     } catch (error) {}
  //   }
  // }, [formBuilderData?.fields])

  // useEffect(() => {
  //   const handler = (changes: any) => {
  //     console.log('changes', changes)
  //     hyperformulaInstance.rebuildAndRecalculate()
  //   }

  //   hyperformulaInstance.on('valuesUpdated', handler)

  //   return () => {
  //     hyperformulaInstance.off('valuesUpdated', handler)
  //   }
  // }, [])

  useEffect(() => {
    if (formData && Object.keys(formData).length > 0) {
      console.log('Form Data:', formData)
      const existingExpressions = hyperformulaInstance.listNamedExpressions()

      Object.entries(formData).forEach(([key, value]) => {
        if (!existingExpressions.includes(`${key}`)) {
          hyperformulaInstance.addNamedExpression(`${key}`, Number(value) || 0)
        } else {
          hyperformulaInstance.changeNamedExpression(
            `${key}`,
            Number(value) || 0
          )
        }
        hyperformulaInstance.getNamedExpressionValue(key)
        console.log(
          `get named ${key}`,
          hyperformulaInstance.getNamedExpressionValue(key)
        )

        // hyperformulaInstance.setCellContents(
        //   { sheet: sheetId, row: 0, col: 0 },
        //   [[Number(value) || 0]]
        // )
      })

      hyperformulaInstance.rebuildAndRecalculate()
      // setCount((prev) => prev + 1)
      try {
        // setTimeout(() => {
        //   hyperformulaInstance.rebuildAndRecalculate()
        // }, 100)
      } catch (error) {}
    }
  }, [formData])

  useEffect(() => {
    const adjustedData = adjustDataDimensions(data, rows, columns)
    if (JSON.stringify(data) !== JSON.stringify(adjustedData)) {
      setData(adjustedData)
    }
  }, [rows, columns])

  const adjustDataDimensions = (
    currentData: any[][],
    rows: number,
    columns: number
  ) => {
    const newData = currentData.map((row) => [...row])
    if (newData.length < rows) {
      for (let i = newData.length; i < rows; i++) {
        newData.push(Array(columns).fill(null))
      }
    } else if (newData.length > rows) {
      newData.length = rows
    }
    newData.forEach((row) => {
      if (row.length < columns) {
        row.push(...Array(columns - row.length).fill(null))
      } else if (row.length > columns) {
        row.length = columns
      }
    })
    return newData
  }

  const handleAfterChange = (changes: any, source: string) => {
    if (!changes || source === 'loadData') return

    const validSheetId = sheetId ?? 0
    const updatedFormulas = [...formulas]

    changes.forEach(([row, col, oldValue, newValue]: any) => {
      if (
        newValue &&
        typeof newValue === 'string' &&
        newValue.startsWith('=')
      ) {
        try {
          updatedFormulas.push({ row, col, formula: newValue })
          setFormulas(updatedFormulas)

          hyperformulaInstance.setCellContents(
            { sheet: validSheetId, row, col },
            [[newValue]]
          )
        } catch (error) {}
      }
    })
    const updatedData = hotTableRef.current?.hotInstance?.getData?.()

    setData(updatedData)

    if (props.onChange) {
      props.onChange(updatedData)
    }
    try {
      hyperformulaInstance.rebuildAndRecalculate()
      // setData(hyperformulaInstance.getSheetValues)
      // console.log(
      //   'Get Sheet Value:',
      //   hyperformulaInstance.getSheetValues(sheetId!)
      // )
    } catch (error) {}
  }

  console.log('hotable', hotTableRef.current?.hotInstance?.getData?.())
  // const handleAfterChange = (changes: any, source: string) => {
  //   if (!changes || source === 'loadData') return

  //   const validSheetId = sheetId ?? 0
  //   const updatedFormulas = [...formulas]

  //   changes.forEach(([row, col, oldValue, newValue]: any) => {
  //     if (
  //       newValue &&
  //       typeof newValue === 'string' &&
  //       newValue.startsWith('=')
  //     ) {
  //       try {
  //         updatedFormulas.push({ row, col, formula: newValue })
  //         setFormulas(updatedFormulas)

  //         // hyperformulaInstance.setCellContents(
  //         //   { sheet: validSheetId, row, col },
  //         //   [[newValue]]
  //         // )
  //       } catch (error) {
  //         console.error('Error setting cell contents:', error)
  //       }
  //     }
  //   })

  //   try {
  //     hyperformulaInstance.rebuildAndRecalculate()

  //     const updatedData = hotTableRef.current?.hotInstance?.getData?.()

  //     setData(updatedData)

  //     if (props.onChange) {
  //       props.onChange(updatedData)
  //     }
  //   } catch (error) {
  //     console.error('Error rebuilding and recalculating formulas:', error)
  //   }
  // }

  console.log('hotable', hotTableRef.current?.hotInstance?.getData?.())

  const handleMergeCells = () => {
    const hotInstance = hotTableRef.current?.hotInstance
    const selected = hotInstance?.getSelected()
    if (selected) {
      const [startRow, startCol, endRow, endCol] = selected[0]
      const newMerge = {
        row: startRow,
        col: startCol,
        rowspan: endRow - startRow + 1,
        colspan: endCol - startCol + 1,
      }

      const updatedMergeCellsConfig = [...mergeCellsConfig, newMerge]
      hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
      setMergeCellsConfig(updatedMergeCellsConfig)

      updateFieldProperties({
        data,
        cellFormats,
        mergeCellsConfig: updatedMergeCellsConfig,
      })
    }
  }

  const handleUnmergeCells = () => {
    const hotInstance = hotTableRef.current?.hotInstance
    const selected = hotInstance?.getSelected()
    if (selected) {
      const [startRow, startCol] = selected[0]
      const mergeCellsPlugin = hotInstance.getPlugin('mergeCells')
      mergeCellsPlugin.unmerge(startRow, startCol)

      const updatedMergeCellsConfig = mergeCellsConfig.filter(
        (cell) => cell.row !== startRow || cell.col !== startCol
      )
      hotInstance.updateSettings({ mergeCells: updatedMergeCellsConfig })
      setMergeCellsConfig(updatedMergeCellsConfig)

      updateFieldProperties({
        data,
        cellFormats,
        mergeCellsConfig: updatedMergeCellsConfig,
      })
    }
  }

  const handleSetAsDate = () => {
    const selected = hotTableRef.current?.hotInstance.getSelected()
    if (selected) {
      const [row, col] = selected[0]
      const newFormats = { ...cellFormats, [`${row}-${col}`]: 'date' as const }
      setCellFormats(newFormats)
      updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
    }
  }

  const handleSetAsCurrency = () => {
    const selected = hotTableRef.current?.hotInstance.getSelected()
    if (selected) {
      const [row, col] = selected[0]
      const newFormats = {
        ...cellFormats,
        [`${row}-${col}`]: 'currency' as const,
      }
      setCellFormats(newFormats)
      updateFieldProperties({ data, cellFormats: newFormats, mergeCellsConfig })
    }
  }

  const updateFieldProperties = (updatedMeta: any) => {
    formBuilderWorksheetActions?.setFieldConfigProperty(props.config?.id!, {
      meta: {
        data,
        formulas,
        mergeCellsConfig,
        ...updatedMeta,
      },
    })
  }

  const cellsHandler = (row: number, col: number) => {
    const cellProperties = {} as Handsontable.CellProperties
    cellProperties.width = DEFAULT_COLUMN_WIDTH
    cellProperties.height = DEFAULT_ROW_HEIGHT

    const format = cellFormats?.[`${row}-${col}`]

    if (format === 'date') {
      cellProperties.renderer = (
        instance,
        td,
        row,
        col,
        prop,
        value,
        cellProperties
      ) =>
        CustomContentRenderer(instance, td, row, col, () => {
          const span = document.createElement('span')
          span.innerText = reformatDate(
            instance.getDataAtCell(row, col) as string
          )
          return span
        })
    } else if (format === 'currency') {
      cellProperties.renderer = (
        instance,
        td,
        row,
        col,
        prop,
        value,
        cellProperties
      ) =>
        CustomContentRenderer(instance, td, row, col, () => {
          const span = document.createElement('span')
          span.innerText = reformatCurrency(
            instance.getDataAtCell(row, col) as string
          )
          return span
        })
    }

    return cellProperties
  }

  return (
    <div
      ref={containerRef}
      className="h-[400px] w-1/2 resize-x overflow-auto border md:w-full"
      style={{ minWidth: '50%', maxWidth: '100%', resize: 'horizontal' }}
      onMouseDown={(e) => e.stopPropagation()}
    >
      <HotTable
        id="mySpreadsheet"
        data={data}
        colHeaders={true}
        rowHeaders={true}
        width="100%"
        height="100%"
        selectionMode="multiple"
        copyPaste={true}
        contextMenu={{
          items: {
            row_above: {},
            row_below: {},
            col_left: {},
            col_right: {},
            remove_row: {},
            remove_col: {},
            clear_column: {},
            mergeCells: { name: 'Merge Cells', callback: handleMergeCells },
            unmergeCells: {
              name: 'Unmerge Cells',
              callback: handleUnmergeCells,
            },
            set_as_date: { name: 'Set as Date', callback: handleSetAsDate },
            set_as_currency: {
              name: 'Set as Currency',
              callback: handleSetAsCurrency,
            },
          },
        }}
        ref={hotTableRef}
        afterChange={handleAfterChange}
        persistentState={true}
        licenseKey="non-commercial-and-evaluation"
        manualColumnResize={false}
        manualRowResize={false}
        autoColumnSize={false}
        autoRowSize={false}
        stretchH="all"
        mergeCells={mergeCellsConfig}
        formulas={{ engine: hyperformulaInstance }}
        cells={cellsHandler}
        colWidths={DEFAULT_COLUMN_WIDTH}
        rowHeights={DEFAULT_ROW_HEIGHT}
      />
    </div>
  )
}

export default registerControl<Properties>(SpreadsheetControl, {
  noDisplayLabel: true,
})
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":star: Xero Boost Days- What's on! :star:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Hey Manchester! \n\n We're excited to kickstart another great week in the office with our new Boost Day Program! :zap: \n\nPlease see below for what's on this week! "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-1: Tuesday, 3rd December",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: *Café Partnership*: Café-style beverages with *Ditto Coffee*, located at 61, Oxford Street, M1 6EQ and now also at Union, Albert Square, M2 6LW. (Please show your Xero ID to claim your free coffee)\n:breakfast: *Breakfast*: Provided by *Balance Kitchen* from *8:30AM* in the kitchen area."
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-2: Wednesday, 4th December",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: *Café Partnership*: Café-style beverages with *Ditto Coffee*, located at 61 Oxford Street, M1 6EQ and now also at Union, Albert Square, M2 6LW. (Please bring your Xero ID to claim your free coffee)\n:Lunch-2: *Lunch*: Provided by *Balance Kitchen* from *12:30PM* in the kitchen area.\n:party: *Social Happy Hour Alert!* Join us this Wednesday from 4:00 PM to 6:00 PM for the all new Socials— happy hour vibes, great company, and good times. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Comms will be via this slack channel, get ready to Boost your workdays!\n\nLove,\nWX Team :party-wx:"
			}
		}
	]
selector .jet-hor-timeline-item__card {
  height: 24VH;
  transition: height 0.3s ease-in-out;
}

selector .jet-hor-timeline-item__card img {
  height: 100%;
  width: auto;
  object-fit: cover;
}

/* Mobile responsiveness */

@media screen and (max-width: 767px) {
  selector .jet-hor-timeline-item__card {
    height: auto;
  }
}






selector .jet-hor-timeline-item__card-arrow {
    background-image: url('https://hamentorit.co.il/wp-content/uploads/2024/09/ZyrmvYcqZb.gif');
    background-size: cover;
}!
import socket
# client code to connect with API bridge
HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 56789    # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    #ID,Type,Symbol,OrderType,TrigPrice,Price,Qty,InstrumentName,StrategyTag"
    # Symbol = Symbol | Expiry | Strike | OptionType
    # TrigPrice = TrigPrice | StopLoss | SquareOff | TrailingTicks
    # StrategyTag = StrategyTag | Port

    #s.sendall(b"8,LE,SBIN,M,1,180,1,EQ,STG11")
    #s.sendall(b"8,SE,RELIANCE,L,1,180,1,EQ,STG11")
   # s.sendall(b"8,SE,HDFC,L,1,1200,100,EQ,STG11")
    #s.sendall(b"8,SE,INFY|30MAY2019|130|PE,L,1,2000,50,OPTSTK,STG11")
    s.sendall(b"8,LE,MARUTI,L,1,180,1,EQ,STG11")

    data = s.recv(1024)

print('Received', repr(data))
'post__in' => array(301, 344, 342, 995, 998, 1001, 1000, 999),
'orderby' => 'post__in', 


=======
$arg = array(
		'post_type' => 'team',
		'posts_per_page' => -1,
		'post__in' => array(301, 344, 342, 995, 998, 1001, 1000, 999),
    	'orderby' => 'post__in', 
);
/* eslint-disable no-promise-executor-return */
import dayjs from 'dayjs';
import _ from 'lodash';
import {
  useEffect, useRef, useState,
} from 'react';
import {
  useRecoilValue, useSetRecoilState,
} from 'recoil';
import { t } from 'ttag';
import {
  beatEventCountState,
  rhythmEventCountState,
  specialEventTypesState, updatedAfibAvgHrState, updatedDailyAfibHrSummariesState,
} from '.';
import { clearApolloCache } from '../../../../../Apollo/apolloClient';
import fetchHolterBeatEventsCount from '../../../../../Apollo/Functions/fetchHolterBeatEventsCount';
import fetchHolterEventIndex from '../../../../../Apollo/Functions/fetchHolterEventIndex';
import fetchHolterEvents from '../../../../../Apollo/Functions/fetchHolterEvents';
import fetchHolterEventsDailyCount from '../../../../../Apollo/Functions/fetchHolterEventsDailyCount';
import fetchHolterRhythmEventsCount from '../../../../../Apollo/Functions/fetchHolterRhythmEventsCount';
import handleCheckSavingAiProcess from '../../../../../Apollo/Functions/handleCheckSavingAiProcess';
import { EMITTER_CONSTANTS } from '../../../../../ConstantsV2';
import {
  AI_COMMAND,
  canShowCountBeatEvents, canShowDurationEvents,
  ECG_EVENT_MENU_OPTIONS, EVENT_COUNT_CONVERT, ID_BOOKMARK_TAB, KEY_CANCEL, KEY_RECOIL, STRIP_EVENT_THUMBNAIL_INFO, TYPE_RHYTHM_EVENT_ENUM,
  typesPersistEventV2,
} from '../../../../../ConstantsV2/aiConstants';
import { convertToDayJS } from '../../../../../UtilsV2/aiUtils';
import { useEmitter, useGetRecoilValue } from '../../../../../UtilsV2/customHooks';
import emitter from '../../../../../UtilsV2/eventEmitter';
import { toastrError } from '../../../../../UtilsV2/toastNotification';
import {
  activeTabState,
  beatChangesState,
  dailyCountState,
  ecgDataMapState,
  eventChangesState,
  eventFilterState,
  eventNewsState,
  eventOptionsState,
  eventOthersState,
  groupEventChangesState,
  isActiveTabState,
  isNotReadyAfterSaveState,
  isRenderViewerEcgState,
  originalDailySummariesState,
  pageIndexState,
  profileAfibAvgHrState,
  reloadEcgViewerState,
  reloadHrChartState,
  reportInfoState,
  selectedDateValueState,
  selectedStripState,
} from '../../Recoil';
import { logError } from '../../handler';
import {
  generateFilterSpecialEventType,
  isAppliedFilterEvent,
} from '../handler';
import { clearCachesBeatHourly } from '../../../../../Store/caches';
import { removeSavingData } from '../../BeatHR/helper';
import { beatOptionsState } from '../../BeatHR/recoil';

const RhythmEventsRecoilDataEffect = (props) => {
  const keyRecoil = KEY_RECOIL.TAB_2;
  const activeButton = useRecoilValue(activeTabState(keyRecoil));
  const getActiveButton = useGetRecoilValue(activeTabState(keyRecoil));
  const getSelectedStrip = useGetRecoilValue(selectedStripState(keyRecoil));
  const getPageIndex = useGetRecoilValue(pageIndexState(keyRecoil));
  const setPageIndex = useSetRecoilState(pageIndexState(keyRecoil));
  const getSelectedDateValue = useGetRecoilValue(selectedDateValueState(keyRecoil));
  const getSpecialEventTypes = useGetRecoilValue(specialEventTypesState);
  const getEventFilter = useGetRecoilValue(eventFilterState(keyRecoil));
  const setDailyCount = useSetRecoilState(dailyCountState(keyRecoil));
  const setUpdatedAfibAvgHr = useSetRecoilState(updatedAfibAvgHrState);
  const setUpdatedDailyAfibHrSummaries = useSetRecoilState(updatedDailyAfibHrSummariesState);
  const setEventChanges = useSetRecoilState(eventChangesState(keyRecoil));
  const setBeatChanges = useSetRecoilState(beatChangesState(keyRecoil));
  const setReloadEcgViewer = useSetRecoilState(reloadEcgViewerState(keyRecoil));
  const setReloadHrChart = useSetRecoilState(reloadHrChartState(keyRecoil));
  const setGroupEventChanges = useSetRecoilState(groupEventChangesState(keyRecoil));
  const isActiveTab = useRecoilValue(isActiveTabState(keyRecoil));
  const setIsNotReadyAfterSaveTab1 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_1));
  const setIsNotReadyAfterSaveTab2 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_2));
  const setIsNotReadyAfterSaveTab3 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_3));
  const getHolterRhythmEventsCount = useGetRecoilValue(rhythmEventCountState);
  const getHolterBeatEventsCount = useGetRecoilValue(beatEventCountState);
  const { studyId, profileId, timezoneOffset } = useRecoilValue(reportInfoState);
  const setEcgDataMap = useSetRecoilState(ecgDataMapState);
  const getEcgDataMap = useGetRecoilValue(ecgDataMapState);
  const setOriginalDailySummaries = useSetRecoilState(originalDailySummariesState);
  const setProfileAfibAvgHr = useSetRecoilState(profileAfibAvgHrState);
  const setEventOthers = useSetRecoilState(eventOthersState(keyRecoil));
  const setEventNews = useSetRecoilState(eventNewsState(keyRecoil));
  const setEventOptions = useSetRecoilState(eventOptionsState(keyRecoil));
  const setIsRenderViewerEcg = useSetRecoilState(isRenderViewerEcgState);
  const setHolterRhythmEventsCount = useSetRecoilState(rhythmEventCountState);
  const setHolterBeatEventsCount = useSetRecoilState(beatEventCountState);
  const setSelectedStrip = useSetRecoilState(selectedStripState(keyRecoil));
  const [doneReset, setDoneReset] = useState(false);
  const setBeatOptions = useSetRecoilState(beatOptionsState(keyRecoil));

  const commandPendingQueue = useRef([]);
  const updateDataMessageQueue = useRef([]);
  const promiseUpdateData = useRef([]);
  const promiseUpdateDataType = useRef([]);
  const isExcutedRef = useRef(false);

  const handleFetchStripEvents = async ({ page, additionalFilter = {} }) => {
    try {
      const type = getActiveButton();
      const validatePage = page <= 0 ? 0 : page;
      const filterHolterEvents = {
        studyId,
        profileId,
        types: [type],
        skip: validatePage * STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit,
        ...additionalFilter,
      };
      const promises = [fetchHolterEvents(
        filterHolterEvents,
        STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit,
        true,
        KEY_CANCEL.API_HOLTER_AI,
      )];
      if (!_.isEmpty(additionalFilter)) {
        const holterEventsCountFilter = {
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        };
        promises.push(
          _.find(ECG_EVENT_MENU_OPTIONS, (x) => x.value === type).type === 'beat'
            ? fetchHolterBeatEventsCount(holterEventsCountFilter, true, KEY_CANCEL.API_HOLTER_AI)
            : fetchHolterRhythmEventsCount(holterEventsCountFilter, true, KEY_CANCEL.API_HOLTER_AI),
        );
      }
      const [{ events }, eventsCount] = await Promise.all(promises);
      if (!_.isEmpty(additionalFilter)) {
        return { events, eventsCount };
      }
      return { events, eventsCount: _.find(ECG_EVENT_MENU_OPTIONS, (x) => x.value === type).type === 'beat' ? getHolterBeatEventsCount() : getHolterRhythmEventsCount() };
    } catch (error) {
      return { events: undefined, eventsCount: 0 };
    }
  };

  const handleReloadEventHrChartV2 = async () => {
    try {
      const type = activeButton;
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
      ];
      await Promise.allSettled(promiseArr);
      if (!_.includes(promiseUpdateDataType.current, 'setReloadHrChart')) {
        promiseUpdateDataType.current.push('setReloadHrChart');
        promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
      }
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadEventDataV2 = async (needUpdateAfibArtifact) => {
    try {
      if (isActiveTab) {
        setIsRenderViewerEcg(false);
      }
      const type = activeButton;
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const additionalFilter = generateFilterSpecialEventType(type, getSpecialEventTypes());
      const eventFilter = getEventFilter();
      if (isAppliedFilterEvent(eventFilter, type)) {
        _.assign(additionalFilter, {
          ...(eventFilter.isHideReviewed && { isReviewed: false }),
          ...(eventFilter.isCapture && { isCaptured: true }),
          ...(eventFilter.sortOrder && (canShowCountBeatEvents.includes(type) || canShowDurationEvents.includes(type)) && {
            sortBy: eventFilter.sortBy || 'countBeats',
            sortOrder: eventFilter.sortOrder,
          }),
        });
      }
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
        fetchHolterEventsDailyCount({
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        }, null, false),
      ];
      const selectedStrip = getSelectedStrip();
      if (selectedStrip?.idEvent) {
        const filterHolterEventIndex = {
          studyId,
          profileId,
          types: [type],
          includedEventId: selectedStrip.idEvent,
          ...additionalFilter,
        };
        promiseArr.push(fetchHolterEventIndex(filterHolterEventIndex, false, KEY_CANCEL.API_HOLTER_AI));
      } else {
        promiseArr.push(new Promise((resolve) => resolve(undefined)));
      }
      const [resultHolterEventsPersistAllDay, resultDailyCount, resultEventIndex] = await Promise.allSettled(promiseArr);
      const dailyCount = resultDailyCount?.status === 'rejected' ? undefined : resultDailyCount.value;
      if (resultEventIndex?.status === 'fulfilled') {
        const eventIndex = resultEventIndex.value;
        if (!_.isNil(eventIndex) && eventIndex >= 0) {
          const page = Math.floor(eventIndex / STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit);
          await handleFetchStripEvents({ page, additionalFilter });
          promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
        } else {
          const pageIndex = getPageIndex();
          const { events, eventsCount } = await handleFetchStripEvents({ page: pageIndex.index, additionalFilter });
          if (_.isEmpty(events)) {
            const totalEvent = eventsCount[EVENT_COUNT_CONVERT[getActiveButton()]]?.count || 0;
            const pageTemp = Math.floor(totalEvent / STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit);
            const page = (totalEvent % STRIP_EVENT_THUMBNAIL_INFO.stripDisplayLimit) === 0 ? pageTemp - 1 : pageTemp;
            promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
          } else {
            promiseUpdateData.current.push(() => setPageIndex({ index: getPageIndex().index }));
          }
        }
      }
      if (needUpdateAfibArtifact) {
        handleReloadEventHrChartV2();
      }
      if (!_.isEmpty(dailyCount)) {
        promiseUpdateData.current.push(() => setDailyCount(dailyCount));
      }
      if (!_.includes(promiseUpdateDataType.current, 'setReloadHrChart')) {
        promiseUpdateDataType.current.push('setReloadHrChart');
        promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
      }
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadEvent = async (msg) => {
    try {
      if (isActiveTab) {
        setIsRenderViewerEcg(false);
      }
      const {
        newEvents, deletedEvents, updatedEvents, deletedEventTypes,
      } = msg;
      const selectedDateValue = getSelectedDateValue();
      const selectedDateString = selectedDateValue ? convertToDayJS(selectedDateValue, timezoneOffset).format('DD-MM-YYYY') : null;
      const types = [TYPE_RHYTHM_EVENT_ENUM.AFIB, TYPE_RHYTHM_EVENT_ENUM.ARTIFACT];
      let needUpdate;
      let needUpdateAfibArtifact; //* Trường hợp sửa artifact hoặc afib xong qua tab event khác save thì hr chart ko update
      if (deletedEventTypes?.length) {
        deletedEventTypes.forEach((type) => {
          if (type === activeButton || type === TYPE_RHYTHM_EVENT_ENUM.TACHY) {
            needUpdate = true;
          } else if (types.includes(type)) {
            needUpdateAfibArtifact = true;
          }
        });
      }
      if (deletedEvents?.length) {
        deletedEvents.forEach((deletedEvent) => {
          if (deletedEvent.type === activeButton || (deletedEvent.type === TYPE_RHYTHM_EVENT_ENUM.TACHY)) {
            needUpdate = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(deletedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (types.includes(deletedEvent.type) && isSameDate) {
              needUpdateAfibArtifact = true;
            }
          }
        });
      }
      if (newEvents?.length) {
        newEvents.forEach((newEvent) => {
          if (newEvent.type === activeButton) {
            needUpdate = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(newEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (types.includes(newEvent.type) && isSameDate) {
              needUpdateAfibArtifact = true;
            }
          }
        });
      }
      if (updatedEvents?.length) {
        updatedEvents.forEach((updatedEvent) => {
          if (updatedEvent.type === activeButton) {
            needUpdate = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(updatedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (types.includes(updatedEvent.type) && isSameDate) {
              needUpdateAfibArtifact = true;
            }
          }
        });
      }
      if (needUpdate) {
        await handleReloadEventDataV2(needUpdateAfibArtifact);
      } else if (needUpdateAfibArtifact || activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
        await handleReloadEventHrChartV2();
      } else if (activeButton === ID_BOOKMARK_TAB) {
        if (!_.includes(promiseUpdateDataType.current, 'setReloadHrChart')) {
          promiseUpdateDataType.current.push('setReloadHrChart');
          promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
        }
      }
      console.log('[rhythmEventsRecoilDataEffect]-RELOAD-EVENT-RHYTHMEVENT', needUpdate, activeButton, needUpdateAfibArtifact);
      if (!_.includes(promiseUpdateDataType.current, 'setReloadEcgViewer')) {
        promiseUpdateDataType.current.push('setReloadEcgViewer');
        promiseUpdateData.current.push(() => setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100)));
      }
      promiseUpdateData.current.push(() => {
        setGroupEventChanges((prev) => {
          if (prev.length === 0) {
            return prev;
          }
          return [];
        });
        let eventChanges = [];
        let eventNews = [];
        let eventOthers = [];

        setEventChanges((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventChanges.push(...filterResult);
          return filterResult;
        });
        setEventOthers((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventOthers.push(...filterResult);
          return filterResult;
        });
        setEventNews((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventNews.push(...filterResult);
          return filterResult;
        });

        // Perform grouping action applicable to undo/redo
        setEventOptions({
          eventNewsState: eventNews,
          eventChangesState: eventChanges,
          eventOthersState: eventOthers,
        });

        eventChanges = [];
        eventNews = [];
        eventOthers = [];
        const selectedStrip = getSelectedStrip();
        if (selectedStrip?.isNew) {
          setSelectedStrip(null);
        }
      });
    } catch (error) {
      logError('Error: ', error);
    }
    return true;
  };

  const handleUpdateBeats = (msg) => {
    const prevEcgDataMap = getEcgDataMap();
    const cloneEcgDataMap = { ...prevEcgDataMap };
    if ((msg.summaries?.length || msg.beatsUpdated?.summaries?.length) && !_.isEmpty(prevEcgDataMap?.data)) {
      _.forEach(msg.summaries || msg.beatsUpdated?.summaries, (summary) => {
        const foundData = _.find(cloneEcgDataMap.data, (x) => x.id === summary.id);
        if (foundData) {
          _.assign(foundData, {
            avgHrs: summary?.avgHrs,
            maxHrs: summary?.maxHrs,
            minHrs: summary?.minHrs,
            beatFinalPath: summary?.beatFinalPath,
            latestBeatPrefix: summary?.latestBeatPrefix,
          });
        }
      });

      const summaryIds = _.map(msg.summaries || msg.beatsUpdated?.summaries, 'id');
      const socketUpdateEcgDataMap = {
        ...cloneEcgDataMap,
        data: _.filter(cloneEcgDataMap.data, (item) => summaryIds.includes(item.id)),
      };
      if (isActiveTab) {
        emitter.emit(EMITTER_CONSTANTS.UPDATE_SOCKET_BEAT_DATA_MAP, socketUpdateEcgDataMap);
      }
    }
    return cloneEcgDataMap;
  };

  const handleReloadBeat = async (msg) => {
    try {
      const cloneEcgDataMap = handleUpdateBeats(msg);
      promiseUpdateData.current.push(() => {
        let beatsChanges = [];

        setBeatChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          const beats = removeSavingData(prev);
          beatsChanges = beats;
          return beats;
        });
        setBeatOptions((prev) => ({ ...prev, beatChangesState: beatsChanges }));

        setEcgDataMap((prev) => {
          if (_.isEqual(prev, cloneEcgDataMap)) {
            return prev;
          }
          return cloneEcgDataMap;
        });
        setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100));
      });
    } catch (error) {
      logError('Failed to reload beat', error);
    }
    return true;
  };

  const fetchEventsCount = async () => {
    try {
      const eventsCountFilter = {
        studyId,
        profileId,
      };
      const promises = [
        fetchHolterBeatEventsCount(eventsCountFilter, false, null, false),
        fetchHolterRhythmEventsCount(eventsCountFilter, false, null, false),
      ];
      const [holterBeatEventsCount, holterRhythmEventsCount] = await Promise.all(promises);
      setHolterBeatEventsCount(holterBeatEventsCount);
      setHolterRhythmEventsCount(holterRhythmEventsCount);
    } catch (error) {
      logError('Failed to fetch holter rhythm events count: ', error);
    }
  };

  const updateEventOutOfPending = _.debounce(async () => {
    await clearApolloCache();
    setIsRenderViewerEcg(false);
    setTimeout(() => {
      setIsRenderViewerEcg(true);
    }, 500);
  }, 2000);

  const batchUpdateData = async () => {
    try {
      await clearApolloCache();
      await clearCachesBeatHourly();
      if (isActiveTab || props.activeTab !== '1') {
        setIsRenderViewerEcg(false);
      }
      const promise = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.EVENT) {
          promise.push(handleReloadEvent(x.msg));
          promise.push(fetchEventsCount());
        }
      });
      const beatPromises = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.BEAT) {
          beatPromises.push(handleReloadBeat(x.msg));
        }
      });
      await Promise.all(beatPromises); // Wait for all beat promises to resolve
      console.log('[rhythmEventsRecoilDataEffect]-COMMANDEXECUTED-1', {
        promise,
        updateDataMessageQueue: updateDataMessageQueue.current,
        promiseUpdateData: promiseUpdateData.current,
      });
      await Promise.all(promise);
      promiseUpdateData.current.forEach((update) => update());
      updateDataMessageQueue.current.length = 0;
    } catch (error) {
      logError('Error: ', error);
    } finally {
      console.log('[rhythmEventsRecoilDataEffect]-COMMANDEXECUTED-2', {
        updateDataMessageQueue: updateDataMessageQueue.current,
        promiseUpdateData: promiseUpdateData.current,
      });
      updateDataMessageQueue.current.length = 0;
      promiseUpdateData.current.length = 0;
      commandPendingQueue.current.length = 0;
      promiseUpdateDataType.current.length = 0;
      emitter.emit(EMITTER_CONSTANTS.RELOAD_EVENT_STRIP);
      if (isActiveTab) {
        setDoneReset(true);
      }
    }
  };

  useEffect(() => {
    if (doneReset) {
      setTimeout(() => {
        emitter.emit(EMITTER_CONSTANTS.AI_LOADING, {
          isLoading: false,
          tab: 'rhythmEvents',
          isExcuted: isExcutedRef.current,
        });
        setDoneReset(false);
        if (isExcutedRef.current) {
          isExcutedRef.current = false;
        }
      }, 2000);
    }
  }, [doneReset]);

  useEmitter(EMITTER_CONSTANTS.EVENTSUPDATED_EVENT, (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.EVENT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        Object.keys(msg).forEach((key) => {
          if (foundMsg.msg[key]) {
            foundMsg.msg[key] = foundMsg.msg[key].concat(msg[key]);
          } else {
            foundMsg.msg[key] = msg[key];
          }
        });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.EVENT,
        msg: _.cloneDeep(msg),
      });
    }
    if (commandPendingQueue.current.length === 0) { // update out of pending command
      updateEventOutOfPending();
    }
  }, [studyId, profileId]);

  useEmitter(EMITTER_CONSTANTS.BEATSUPDATED_EVENT, async (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.BEAT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        _.assign(foundMsg, { msg });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.BEAT,
        msg,
      });
    }
  }, []);

  useEmitter(EMITTER_CONSTANTS.DAILY_SUMMARY_UPDATED, (msg) => {
    setOriginalDailySummaries((prev) => {
      if (msg) {
        const cloneDailySummaries = _.cloneDeep(prev);
        _.forEach(msg, (dailySummary) => {
          const foundDailySummary = _.find(cloneDailySummaries, (x) => x.date === dailySummary.date);
          if (foundDailySummary) {
            _.assign(foundDailySummary, dailySummary);
          }
        });
        return cloneDailySummaries;
      }
      return prev;
    });
  }, []);

  useEmitter(EMITTER_CONSTANTS.AFIB_HR_SUMMARY_UPDATED, (msg) => {
    const { afibAvgHr } = msg;
    setProfileAfibAvgHr(afibAvgHr);
    setUpdatedAfibAvgHr(undefined);
    setUpdatedDailyAfibHrSummaries([]);
  }, []);

  useEmitter(EMITTER_CONSTANTS.AI_PROCESS_SAVED, async (msg) => {
    await batchUpdateData();
    setIsNotReadyAfterSaveTab2(false);
  }, [activeButton, studyId, profileId, isActiveTab, props.activeTab]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_PENDING, (msg) => {
    //* Khi 1 user save, BE gửi command pending về tuỳ theo số lượng api gọi lúc save, push command vào mảng và khi
    // có socket command execute thì remove => khi mảng về 0 thì get hết data nhận đc trong mảng updateDataMessage => update UI
    if (msg.messageId !== profileId) return;
    emitter.emit(EMITTER_CONSTANTS.AI_LOADING, { isLoading: true, tab: 'rhythmEvents' });
    commandPendingQueue.current.push(msg.command);
  }, [profileId]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_EXECUTED, async (msg) => {
    // msg.command: update-events, update-beats, updateHolterHrDailySummary
    // updateHolterProfile, generate-report-comments
    if (msg.messageId !== profileId) return;
    if (msg.command === 'updateHolterProfile' || msg.command === 'generate-report-comments') return;
    console.log('[rhythmEventsRecoilDataEffect]-COMMANDEXECUTED-BEFORE', {
      msg,
      commandPendingQueue: commandPendingQueue.current,
      updateDataMessageQueue: updateDataMessageQueue.current,
    });
    const foundIndexCommand = commandPendingQueue.current.findIndex((command) => command === msg.command);
    if (foundIndexCommand !== -1) {
      commandPendingQueue.current.splice(foundIndexCommand, 1);
    }
    //* Finish all command
    if (commandPendingQueue.current.length === 0) {
      isExcutedRef.current = true;
      if (isActiveTab) {
        if (updateDataMessageQueue.current.length !== 0) {
          //* Announce this tab have data to update
          emitter.emit(EMITTER_CONSTANTS.AI_UPDATE_TAB, '2');
          const { beats, events, strips } = await handleCheckSavingAiProcess({
            studyId,
            profileId,
          });
          if (!beats) {
            setIsNotReadyAfterSaveTab1(true);
          }
          if (!strips) {
            setIsNotReadyAfterSaveTab3(true);
          }
          await batchUpdateData();
        } else {
          setDoneReset(true);
        }
      } else {
        await batchUpdateData();
      }
    }
  }, [activeButton, isActiveTab, studyId, profileId, props.activeTab]);

  return null;
};

export default RhythmEventsRecoilDataEffect;
/* eslint-disable no-promise-executor-return */
import dayjs from 'dayjs';
import _ from 'lodash';
import {
  useEffect,
  useRef,
  useState,
} from 'react';
import {
  useRecoilState,
  useRecoilValue,
  useSetRecoilState,
} from 'recoil';
import { t } from 'ttag';
import {
  beatOptionsState,
  dailySummariesCombineState,
  dataHeatmapChartState,
  dataHeatmapChartStatusState,
  generateDefaultHeatmapState,
  listOriginReviewedCellsState,
  listReviewedCellsState,
  listSelectedCellsState,
  listUnReviewedCellsState,
  resetAppliedBulkChangesState,
  rrHeatMapCellChangesState,
  rrOverviewOriginState,
  rrOverviewState,
  totalStripState,
  updatedDailySummariesState,
} from '.';
import fetchHolterBeatEventsCount from '../../../../../Apollo/Functions/fetchHolterBeatEventsCount';
import fetchHolterEventIndex from '../../../../../Apollo/Functions/fetchHolterEventIndex';
import fetchHolterEvents from '../../../../../Apollo/Functions/fetchHolterEvents';
import fetchHolterEventsDailyCount from '../../../../../Apollo/Functions/fetchHolterEventsDailyCount';
import fetchHolterRhythmEventsCount from '../../../../../Apollo/Functions/fetchHolterRhythmEventsCount';
import fetchHolterRrHeatMapCount from '../../../../../Apollo/Functions/fetchHolterRrHeatMapCount';
import fetchHolterRrHeatMapOverview from '../../../../../Apollo/Functions/fetchHolterRrHeatMapOverview';
import handleCheckSavingAiProcess from '../../../../../Apollo/Functions/handleCheckSavingAiProcess';
import { clearApolloCache } from '../../../../../Apollo/apolloClient';
import { EMITTER_CONSTANTS } from '../../../../../ConstantsV2';
import {
  AI_COMMAND,
  EVENT_COUNT_CONVERT,
  KEY_CANCEL,
  KEY_RECOIL,
  STRIP_AFIB_THUMBNAIL_INFO,
  STRIP_ARTIFACT_THUMBNAIL_INFO,
  TYPE_RHYTHM_EVENT_ENUM,
  typesPersistEventV2,
} from '../../../../../ConstantsV2/aiConstants';
import { resetHistoryStateRecoil } from '../../../../../Store/dbHistoryStateRecoil';
import { getDataStateRecoil } from '../../../../../Store/dbStateRecoil';
import { convertToDayJS } from '../../../../../UtilsV2/aiUtils';
import {
  useEmitter,
  useGetRecoilValue,
} from '../../../../../UtilsV2/customHooks';
import emitter from '../../../../../UtilsV2/eventEmitter';
import { toastrError } from '../../../../../UtilsV2/toastNotification';
import {
  activeTabState,
  beatChangesState,
  dailyArtifactCountState,
  dailyCountState,
  ecgDataMapState,
  eventChangesState,
  eventFilterState,
  eventNewsState,
  eventOptionsState,
  eventOthersState,
  groupEventChangesState,
  isActiveTabState,
  isNotReadyAfterSaveState,
  isRenderViewerEcgState,
  originalDailySummariesState,
  pageIndexState,
  profileAfibAvgHrState,
  reloadEcgViewerState,
  reloadHrChartState,
  reportInfoState,
  selectedDateValueState,
  selectedStripState,
} from '../../Recoil';
import { isAppliedFilterEvent } from '../../RhythmEvents/handler';
import { beatEventCountState, rhythmEventCountState } from '../../RhythmEvents/recoil';
import { logError } from '../../handler';
import { formatDataChart } from '../rrInterval/heatMapChart/handler';
import { DATA_HEATMAP_STATUS } from './model';
import { clearCachesBeatHourly } from '../../../../../Store/caches';
import { removeSavingData } from '../helper';

const BeatHrRecoilDataEffect = () => {
  const keyRecoil = KEY_RECOIL.TAB_1;
  const activeButton = useRecoilValue(activeTabState(keyRecoil));
  const getActiveButton = useGetRecoilValue(activeTabState(keyRecoil));
  const getSelectedStrip = useGetRecoilValue(selectedStripState(keyRecoil));
  const selectedDateValue = useRecoilValue(selectedDateValueState(keyRecoil));
  const getSelectedDateValue = useGetRecoilValue(selectedDateValueState(keyRecoil));
  const setBeatChanges = useSetRecoilState(beatChangesState(keyRecoil));
  const setEventChanges = useSetRecoilState(eventChangesState(keyRecoil));
  const setTotalStrip = useSetRecoilState(totalStripState);
  const setDailyCount = useSetRecoilState(dailyCountState(keyRecoil));
  const setArtifactDailyCount = useSetRecoilState(dailyArtifactCountState(keyRecoil));
  const setDailySummariesCombine = useSetRecoilState(dailySummariesCombineState);
  const setRrOverview = useSetRecoilState(rrOverviewState);
  const getRrOverview = useGetRecoilValue(rrOverviewState);
  const setRrOverviewOrigin = useSetRecoilState(rrOverviewOriginState);
  const getPageIndex = useGetRecoilValue(pageIndexState(keyRecoil));
  const setPageIndex = useSetRecoilState(pageIndexState(keyRecoil));
  const [updatedDailySummaries, setUpdatedDailySummaries] = useRecoilState(updatedDailySummariesState);
  const setReloadEcgViewer = useSetRecoilState(reloadEcgViewerState(keyRecoil));
  const setReloadHrChart = useSetRecoilState(reloadHrChartState(keyRecoil));
  const getDataHeatmapChart = useGetRecoilValue(dataHeatmapChartState);
  const getDataHeatmapChartStatus = useGetRecoilValue(dataHeatmapChartStatusState);
  const getListReviewedCells = useGetRecoilValue(listReviewedCellsState);
  const getListUnReviewedCells = useGetRecoilValue(listUnReviewedCellsState);
  const setListReviewedCells = useSetRecoilState(listReviewedCellsState);
  const setListUnReviewedCells = useSetRecoilState(listUnReviewedCellsState);
  const setDataHeatmapChart = useSetRecoilState(dataHeatmapChartState);
  const setDataHeatmapChartStatus = useSetRecoilState(dataHeatmapChartStatusState);
  const setListOriginReviewedCells = useSetRecoilState(listOriginReviewedCellsState);
  const setGroupEventChanges = useSetRecoilState(groupEventChangesState(keyRecoil));
  const getEventFilter = useGetRecoilValue(eventFilterState(keyRecoil));
  const isActiveTab = useRecoilValue(isActiveTabState(keyRecoil));
  const setIsNotReadyAfterSaveTab1 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_1));
  const setIsNotReadyAfterSaveTab2 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_2));
  const setIsNotReadyAfterSaveTab3 = useSetRecoilState(isNotReadyAfterSaveState(KEY_RECOIL.TAB_3));
  const getHolterRhythmEventsCount = useGetRecoilValue(rhythmEventCountState);
  const getListSelectedCells = useGetRecoilValue(listSelectedCellsState);
  const setListSelectedCells = useSetRecoilState(listSelectedCellsState);
  const setEventOthers = useSetRecoilState(eventOthersState(keyRecoil));
  const setEventNews = useSetRecoilState(eventNewsState(keyRecoil));
  const setEventOptions = useSetRecoilState(eventOptionsState(keyRecoil));
  const setHolterRhythmEventsCount = useSetRecoilState(rhythmEventCountState);
  const setHolterBeatEventsCount = useSetRecoilState(beatEventCountState);
  const setSelectedStrip = useSetRecoilState(selectedStripState(keyRecoil));
  const setIsRenderViewerEcg = useSetRecoilState(isRenderViewerEcgState);
  const setRrHeatMapCellChanges = useSetRecoilState(rrHeatMapCellChangesState);
  const setResetAppliedBulkChanges = useSetRecoilState(resetAppliedBulkChangesState);
  const setBeatOptions = useSetRecoilState(beatOptionsState(keyRecoil));

  const {
    studyId,
    profileId,
    timezoneOffset,
  } = useRecoilValue(reportInfoState);
  const [originalDailySummaries, setOriginalDailySummaries] = useRecoilState(originalDailySummariesState);
  const setEcgDataMap = useSetRecoilState(ecgDataMapState);
  const getEcgDataMap = useGetRecoilValue(ecgDataMapState);
  const setProfileAfibAvgHr = useSetRecoilState(profileAfibAvgHrState);

  const commandPendingQueue = useRef([]);
  const updateDataMessageQueue = useRef([]);
  const promiseUpdateData = useRef([]);
  const isExcutedRef = useRef(false);

  const [doneReset, setDoneReset] = useState(false);
  const [doneSetListOriginReviewedCells, setDoneSetListOriginReviewedCells] = useState(true);

  const formatRrOverview = (rrOverview) => {
    const result = generateDefaultHeatmapState({
      reviewed: 1,
      total: 1,
    });
    _.forEach(rrOverview, (x) => {
      result[x.rrHeatMapType] = x.total === 0 ? {
        reviewed: 1,
        total: 1,
      } : {
        reviewed: x.reviewed,
        total: x.total,
      };
    });
    return result;
  };

  const handleFetchRrOverview = async (isFistFetch = false) => {
    // check data from indexdb, if true, no need to fetch data from server
    const rrOver = await getDataStateRecoil('rrOverviewState');
    if (isFistFetch && rrOver) {
      return {};
    }
    try {
      const rrOverview = await fetchHolterRrHeatMapOverview({
        studyId,
        profileId,
      }, null, false);

      const formattedRrOverview = formatRrOverview(rrOverview);
      setRrOverview(formattedRrOverview);
      setRrOverviewOrigin(formattedRrOverview);
    } catch (error) {
      logError('Failed to fetch rr histogram overview', error);
    }
    return {};
  };

  const handleFetchStripEventsArtifact = async (page) => {
    if (!selectedDateValue) {
      return undefined;
    }
    try {
      const validatePage = page <= 0 ? 0 : page;
      const filterHolterEvents = {
        studyId,
        profileId,
        types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
        startRange: {
          start: selectedDateValue,
          stop: dayjs(selectedDateValue).add(1, 'days').toISOString(),
        },
        skip: validatePage * STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit,
      };
      const { events } = await fetchHolterEvents(
        filterHolterEvents,
        STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit,
        true,
        KEY_CANCEL.API_HOLTER_AI,
      );
      return events;
    } catch (error) {
      return undefined;
    }
  };

  const handleFetchStripEventsAfib = async ({ page, additionalFilter = {} }) => {
    try {
      const type = getActiveButton();
      const validatePage = page <= 0 ? 0 : page;
      const filterHolterEvents = {
        studyId,
        profileId,
        types: [type],
        skip: validatePage * STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit,
        ...additionalFilter,
      };
      const promises = [fetchHolterEvents(
        filterHolterEvents,
        STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit,
        true,
        KEY_CANCEL.API_HOLTER_AI,
      )];
      if (!_.isEmpty(additionalFilter)) {
        const holterEventsCountFilter = {
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        };
        promises.push(fetchHolterRhythmEventsCount(holterEventsCountFilter, true, KEY_CANCEL.API_HOLTER_AI));
      }
      const [{ events }, eventsCount] = await Promise.all(promises);
      if (!_.isEmpty(additionalFilter)) {
        return { events, eventsCount };
      }
      return { events, eventsCount: getHolterRhythmEventsCount() };
    } catch (error) {
      return { events: undefined, eventsCount: 0 };
    }
  };

  const handleReloadAfibV2 = async () => {
    try {
      const type = getActiveButton();
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const additionalFilter = {};
      const eventFilter = getEventFilter();
      if (isAppliedFilterEvent(eventFilter, type)) {
        _.assign(additionalFilter, {
          ...(eventFilter.isHideReviewed && { isReviewed: false }),
          ...(eventFilter.isCapture && { isCaptured: true }),
        });
      }
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
        fetchHolterEventsDailyCount({
          studyId,
          profileId,
          types: [type],
          ...additionalFilter,
        }, null, false),
      ];
      const selectedStrip = getSelectedStrip();
      if (selectedStrip?.idEvent) {
        const filterHolterEventIndex = {
          studyId,
          profileId,
          types: [type],
          includedEventId: selectedStrip.idEvent,
          ...additionalFilter,
        };
        promiseArr.push(fetchHolterEventIndex(filterHolterEventIndex, false, KEY_CANCEL.API_HOLTER_AI));
      } else {
        promiseArr.push(new Promise((resolve) => resolve(undefined)));
      }
      const [resultHolterEventsPersistAllDay, resultDailyCount, resultEventIndex] = await Promise.allSettled(promiseArr);
      const dailyCount = resultDailyCount?.status === 'rejected' ? undefined : resultDailyCount.value;
      if (resultEventIndex?.status === 'fulfilled') {
        const eventIndex = resultEventIndex.value;
        if (!_.isNil(eventIndex) && eventIndex >= 0) {
          const page = Math.floor(eventIndex / STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit);
          await handleFetchStripEventsAfib({ page, additionalFilter });
          promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
        } else {
          const pageIndex = getPageIndex();
          const { events, eventsCount } = await handleFetchStripEventsAfib({ page: pageIndex.index, additionalFilter });
          if (_.isEmpty(events)) {
            const totalEvent = eventsCount[EVENT_COUNT_CONVERT[getActiveButton()]]?.count || 0;
            const pageTemp = Math.floor(totalEvent / STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit);
            const page = (totalEvent % STRIP_AFIB_THUMBNAIL_INFO.stripDisplayLimit) === 0 ? pageTemp - 1 : pageTemp;
            promiseUpdateData.current.push(() => setPageIndex({ index: page < 0 ? 0 : page }));
          } else {
            promiseUpdateData.current.push(() => setPageIndex({ index: getPageIndex().index }));
          }
        }
      }
      if (!_.isEmpty(dailyCount)) {
        if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
          promiseUpdateData.current.push(() => setArtifactDailyCount(dailyCount));
        } else {
          promiseUpdateData.current.push(() => setDailyCount(dailyCount));
        }
      }
      promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadAfibHrChartV2 = async () => {
    try {
      const selectedDateValue = getSelectedDateValue();
      const startSearchDate = selectedDateValue;
      const stopSearchDate = selectedDateValue ? dayjs(selectedDateValue).add(1, 'days').toISOString() : null;
      const promiseArr = [
        selectedDateValue ? fetchHolterEvents({
          studyId,
          profileId,
          types: typesPersistEventV2,
          startSearchDate,
          stopSearchDate,
        }, 0, true, KEY_CANCEL.API_HOLTER_AI) : undefined,
      ];
      await Promise.allSettled(promiseArr);
      promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Failed to fetch reload data: ', error);
      toastrError(error.message, t`Error`);
    }
  };

  const handleReloadArtifact = async (reloadAll = false) => {
    try {
      // Thumbnail
      const filterDailyCount = {
        studyId,
        profileId,
        types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
      };
      const promiseArr = [
        fetchHolterEventsDailyCount(filterDailyCount, null, false),
      ];
      const selectedDateValue = getSelectedDateValue();
      if (reloadAll) {
        // Strip event
        const selectedStrip = getSelectedStrip();
        if (selectedStrip?.idEvent && selectedDateValue) {
          const filterHolterEventIndex = {
            studyId,
            profileId,
            types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
            startRange: {
              start: selectedDateValue,
              stop: dayjs(selectedDateValue).add(1, 'days').toISOString(),
            },
            includedEventId: selectedStrip.idEvent,
          };
          promiseArr.push(fetchHolterEventIndex(filterHolterEventIndex, false, KEY_CANCEL.API_HOLTER_AI));
        } else {
          promiseArr.push(new Promise((resolve) => resolve(undefined)));
        }
        if (selectedDateValue) {
          // Hr chart: fetch to cache only
          const filterHolterEvents = {
            studyId,
            profileId,
            types: [TYPE_RHYTHM_EVENT_ENUM.ARTIFACT],
            startSearchDate: selectedDateValue,
            stopSearchDate: dayjs(selectedDateValue).add(1, 'days').toISOString(),
          };
          promiseArr.push(fetchHolterEvents(filterHolterEvents, 0, true, KEY_CANCEL.API_HOLTER_AI));
        }
      }
      const [resultDailyCount, resultEventIndex, resultHolterEventsAllDay] = await Promise.allSettled(promiseArr);
      const dailyCount = resultDailyCount?.status === 'rejected' ? undefined : resultDailyCount.value;
      if (resultEventIndex?.status === 'fulfilled' && reloadAll) {
        const eventIndex = resultEventIndex.value;
        if (!_.isNil(eventIndex) && eventIndex >= 0) {
          const page = Math.floor(eventIndex / STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit);
          await handleFetchStripEventsArtifact(page);
          promiseUpdateData.current.push(() => {
            if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
              setPageIndex({ index: page < 0 ? 0 : page });
            }
          });
        } else {
          const pageIndex = getPageIndex();
          const events = await handleFetchStripEventsArtifact(pageIndex.index);
          if (_.isEmpty(events)) {
            const currentSelectedDateValue = getSelectedDateValue();
            const totalEvent = _.find(dailyCount, (x) => x.date === currentSelectedDateValue)?.count || 0;
            const pageTemp = Math.floor(totalEvent / STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit);
            const page = (totalEvent % STRIP_ARTIFACT_THUMBNAIL_INFO.stripDisplayLimit) === 0 ? pageTemp - 1 : pageTemp;
            promiseUpdateData.current.push(() => {
              if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
                setPageIndex({ index: page < 0 ? 0 : page });
              }
            });
          } else {
            promiseUpdateData.current.push(() => {
              if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
                setPageIndex({ index: getPageIndex().index });
              }
            });
          }
        }
      }
      if (!_.isEmpty(dailyCount)) {
        const currentSelectedDateValue = getSelectedDateValue();
        const foundDailyCount = _.find(dailyCount, (x) => x.date === currentSelectedDateValue)?.count;
        promiseUpdateData.current.push(() => {
          if (getActiveButton() === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
            setTotalStrip(foundDailyCount ?? 0);
            setArtifactDailyCount(dailyCount);
          } else {
            setDailyCount(dailyCount);
          }
        });
      }
      promiseUpdateData.current.push(() => setReloadHrChart((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Error: ', error);
      toastrError(error.message, t`Error`);
    }
    return true;
  };

  const handleReloadEvent = async (msg) => {
    if (isActiveTab) {
      setIsRenderViewerEcg(false);
    }
    try {
      const {
        newEvents, updatedEvents, deletedEvents, deletedEventTypes,
      } = msg;
      // Reload if user in artifact areas and event updated is in selected date
      const selectedDateValue = getSelectedDateValue();
      const selectedDateString = selectedDateValue ? convertToDayJS(selectedDateValue, timezoneOffset).format('DD-MM-YYYY') : null;
      const types = [TYPE_RHYTHM_EVENT_ENUM.AFIB, TYPE_RHYTHM_EVENT_ENUM.ARTIFACT];
      let needUpdateArtifact;
      let needUpdateAfib;
      if (deletedEventTypes?.length && !(needUpdateArtifact || needUpdateAfib)) {
        deletedEventTypes.forEach((type) => {
          if (types.includes(type) && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else if (type === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT && activeButton === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
            needUpdateArtifact = true;
          }
        });
      }
      if (deletedEvents?.length && !(needUpdateArtifact || needUpdateAfib)) {
        deletedEvents.forEach((deletedEvent) => {
          if (deletedEvent.type === activeButton && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(deletedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (deletedEvent.type === activeButton && isSameDate) {
              needUpdateArtifact = true;
            }
          }
        });
      }
      if (updatedEvents?.length && !(needUpdateArtifact || needUpdateAfib)) {
        updatedEvents.forEach((updatedEvent) => {
          if (updatedEvent.type === activeButton && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(updatedEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (updatedEvent.type === activeButton && isSameDate) {
              needUpdateArtifact = true;
            }
          }
        });
      }
      if (newEvents?.length && !(needUpdateArtifact || needUpdateAfib)) {
        newEvents.forEach((newEvent) => {
          if (newEvent.type === activeButton && activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
            needUpdateAfib = true;
          } else {
            const isSameDate = selectedDateString === convertToDayJS(newEvent.start, timezoneOffset).format('DD-MM-YYYY');
            if (newEvent.type === activeButton && isSameDate) {
              needUpdateArtifact = true;
            }
          }
        });
      }
      if (needUpdateArtifact) {
        await handleReloadArtifact(true);
      } else if (needUpdateAfib) {
        await handleReloadAfibV2();
      } else if (activeButton === TYPE_RHYTHM_EVENT_ENUM.ARTIFACT) {
        await handleReloadArtifact();
      } else if (activeButton === TYPE_RHYTHM_EVENT_ENUM.AFIB) {
        await handleReloadAfibHrChartV2();
      }
      console.log('[beatHrRecoilDataEffect]-RELOAD-EVENT-BEATHR', needUpdateArtifact, activeButton);
      promiseUpdateData.current.push(() => {
        setGroupEventChanges((prev) => {
          if (prev.length === 0) {
            return prev;
          }
          return [];
        });

        let eventChanges = [];
        let eventNews = [];
        let eventOthers = [];

        setEventChanges((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventChanges.push(...filterResult);
          return filterResult;
        });
        setEventOthers((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventOthers.push(...filterResult);
          return filterResult;
        });
        setEventNews((prev) => {
          let count = 0;
          const filterResult = prev.filter((x) => {
            if (x.isSaving) {
              count += 1;
              return false;
            }
            return true;
          });
          if (count === 0) {
            return prev;
          }
          eventNews.push(...filterResult);
          return filterResult;
        });
        setEventOptions({
          eventNewsState: eventNews,
          eventChangesState: eventChanges,
          eventOthersState: eventOthers,
        });
        setTimeout(() => {
          resetHistoryStateRecoil();
        }, 200);
        const selectedStrip = getSelectedStrip();
        if (selectedStrip?.isNew) {
          setSelectedStrip(null);
        }
        eventChanges = [];
        eventNews = [];
        eventOthers = [];
      });
      promiseUpdateData.current.push(() => setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100)));
    } catch (error) {
      logError('Error: ', error);
    }
  };

  const updateCellsStatus = async (listDataHeatmapChart) => {
    const resultListReviewedCells = {};
    const resultListUnReviewedCells = {};
    const resultListOriginReviewedCells = {};

    const listUnReviewedCells = getListUnReviewedCells();

    const dataHeatmapChart = getDataHeatmapChart();
    const listReviewedCells = getListReviewedCells();

    const listSelectedCells = _.filter(getListSelectedCells(), (x) => !_.isNaN(Number(x.id)));
    const newListSelectedCells = [];
    let isSetListSelectedCells = false;
    const activeButton = getActiveButton();

    _.forEach(listDataHeatmapChart, (newDataHeatmapChart, key) => {
      const {
        listReviewedCells: currentListReviewedCells,
        listOriginReviewedCells,
      } = formatDataChart({
        currentDataHeatmapChart: newDataHeatmapChart,
        type: key,
      });
      resultListOriginReviewedCells[key] = listOriginReviewedCells;
      const oldDataHeatmapChart = dataHeatmapChart[key];

      const oldListReviewedCells = listReviewedCells[key];

      const studyId2 = window.location.pathname.split('/')[2];
      const defaultHeatmapState = JSON.parse(localStorage.getItem(`defaultValueHeatmap-${Number(studyId2)}`));

      if (defaultHeatmapState) {
        const resultRrOverviewCells = getRrOverview();
        defaultHeatmapState[key] = {
          newValue: {
            listReviewedCells: listReviewedCells[key],
            listUnReviewedCells: [],
            listSelectedCells: [],
            activeButton: key,
            markCells: 'initialize',
            resetData: true,
            rrOverview: resultRrOverviewCells,
          },
        };
        localStorage.setItem(`defaultValueHeatmap-${Number(studyId2)}`, JSON.stringify(defaultHeatmapState));
      }

      const newListReviewedCells = [];
      /* Điều kiện của list review mới:
        - Có trong list review hiện tại (list review được update trong thời gian saving) và không bị mất đi trong list data mới
        - Không nằm trong list data hiện tại nhưng có trong list data mới và có cờ isRevewed = true
      */
      let isSetListReviewedCells = false;

      _.forEach(currentListReviewedCells, (cells) => {
        // check trong list review
        const isInListOldReviewed = _.some(oldListReviewedCells, { id: cells.id });
        if (isInListOldReviewed) {
          // Có trong list review hiện tại (list review được update trong thời gian saving) và không bị mất đi trong list data mới
          newListReviewedCells.push(cells);
          return;
        }
        // check trong list data heatmap
        const isInListOldData = _.some(oldDataHeatmapChart, { id: cells.id });
        if (!isInListOldData) {
          // Không nằm trong list data hiện tại nhưng có trong list data mới và có cờ isRevewed = true
          isSetListReviewedCells = true;
          newListReviewedCells.push(cells);
        }
      });

      _.forEach(oldListReviewedCells, (cells) => {
        const isInListNewData = _.some(newDataHeatmapChart, { id: cells.id });

        if (!isInListNewData) {
          isSetListReviewedCells = true;
          return;
        }

        const isInCurrentList = _.some(newListReviewedCells, { id: cells.id });
        if (!isInCurrentList) {
          // Có trong list review hiện tại (list review được update trong thời gian saving) và không bị mất đi trong list data mới
          newListReviewedCells.push(cells);
        }
      });

      if (isSetListReviewedCells) {
        resultListReviewedCells[key] = newListReviewedCells;
      }
      // reset list unreview
      if (listUnReviewedCells[key]?.length > 0) {
        resultListUnReviewedCells[key] = [];
      }

      if (key === activeButton) {
        // Nếu có item không nằm trong list hiện tại (sau khi save bị xoá cell) hoặc nằm trong nhưng value thay đổi thì set reload
        _.forEach(listSelectedCells, (cell) => {
          let newDataValue;
          const isInNewData = _.some(newDataHeatmapChart, (item) => {
            if (item.id === cell.id) {
              newDataValue = item.count;
              return true;
            }
            return false;
          });
          if (isInNewData) {
            const newCell = { ...cell, value: newDataValue };
            if (cell.value !== newDataValue) {
              isSetListSelectedCells = true;
            }
            newListSelectedCells.push(newCell);
            return;
          }
          isSetListSelectedCells = true;
        });
      }
    });

    if (!_.isEmpty(resultListReviewedCells)) {
      setListReviewedCells((prev) => ({
        ...prev,
        ...resultListReviewedCells,
      }));
    }

    if (!_.isEmpty(resultListUnReviewedCells)) {
      setListUnReviewedCells((prev) => ({
        ...prev,
        ...resultListUnReviewedCells,
      }));
    }

    setListOriginReviewedCells(resultListOriginReviewedCells);
    if (isSetListSelectedCells) {
      emitter.emit(EMITTER_CONSTANTS.UPDATE_RELOAD_BEAT, newListSelectedCells);
      setListSelectedCells(newListSelectedCells);
    } else {
      emitter.emit(EMITTER_CONSTANTS.UPDATE_RELOAD_BEAT);
    }
  };

  const fetchDataHeatmapChart = async (key) => {
    try {
      const filter = {
        studyId,
        profileId,
        rrHeatMapType: key,
      };
      const newDataHeatmapChart = await fetchHolterRrHeatMapCount(filter, null, false);
      return {
        [key]: newDataHeatmapChart,
      };
    } catch (error) {
      logError('Failed to fetch rr heatmap data', error);
      toastrError(error.message);
      return {};
    }
  };

  const handleReloadRrHeatMap = async () => {
    await clearApolloCache();
    const promiseArr = [handleFetchRrOverview()];

    _.forEach(getDataHeatmapChartStatus(), (value, key) => {
      if (value === DATA_HEATMAP_STATUS.SUCCESS || value === DATA_HEATMAP_STATUS.EMPTY) {
        promiseArr.push(fetchDataHeatmapChart(key));
      }
    });

    const data = await Promise.all(promiseArr);
    const newDataHeatmapChart = {};
    const newDataHeatMapChartStatus = {};
    _.forEach(data, (value) => {
      if (!_.isEmpty(value)) {
        _.assign(newDataHeatmapChart, value);
      }
    });

    Object.keys(newDataHeatmapChart).forEach((key) => {
      if (_.isEmpty(newDataHeatmapChart[key])) {
        newDataHeatMapChartStatus[key] = DATA_HEATMAP_STATUS.EMPTY;
      } else {
        newDataHeatMapChartStatus[key] = DATA_HEATMAP_STATUS.SUCCESS;
      }
    });
    setDataHeatmapChart((prev) => ({
      ...prev,
      ...newDataHeatmapChart,
    }));
    setDataHeatmapChartStatus((prev) => ({
      ...prev,
      ...newDataHeatMapChartStatus,
    }));
    // use setTimeOut in order to waiting all setState in recoil
    updateCellsStatus(newDataHeatmapChart);

    setTimeout(() => {
      emitter.emit(EMITTER_CONSTANTS.UPDATE_HEATMAP_CHART_DATA);
    }, 0);
  };

  const handleUpdateBeats = (msg) => {
    const prevEcgDataMap = getEcgDataMap();
    const cloneEcgDataMap = { ...prevEcgDataMap };
    if ((msg.summaries?.length || msg.beatsUpdated?.summaries?.length) && !_.isEmpty(prevEcgDataMap?.data)) {
      _.forEach(msg.summaries || msg.beatsUpdated?.summaries, (summary) => {
        const foundData = _.find(cloneEcgDataMap.data, (x) => x.id === summary.id);
        if (foundData) {
          _.assign(foundData, {
            avgHrs: summary?.avgHrs,
            maxHrs: summary?.maxHrs,
            minHrs: summary?.minHrs,
            beatFinalPath: summary?.beatFinalPath,
            latestBeatPrefix: summary?.latestBeatPrefix,
          });
        }
      });
      const summaryIds = _.map(msg.summaries || msg.beatsUpdated?.summaries, 'id');
      const socketUpdateEcgDataMap = {
        ...cloneEcgDataMap,
        data: _.filter(cloneEcgDataMap.data, (item) => summaryIds.includes(item.id)),
      };
      if (isActiveTab) {
        emitter.emit(EMITTER_CONSTANTS.UPDATE_SOCKET_BEAT_DATA_MAP, socketUpdateEcgDataMap);
      }
    }
    return cloneEcgDataMap;
  };

  const handleReloadBeat = async (msg) => {
    try {
      const cloneEcgDataMap = handleUpdateBeats(msg);
      promiseUpdateData.current.push(() => {
        let rrHeatMapCellChanges = [];
        const resetAppliedBulkChanges = [];
        let beatsChanges = [];
        setRrHeatMapCellChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          rrHeatMapCellChanges = removeSavingData(prev);
          return rrHeatMapCellChanges;
        });
        setResetAppliedBulkChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          resetAppliedBulkChanges.push(...removeSavingData(prev));
          return resetAppliedBulkChanges;
        });
        setBeatChanges((prev) => {
          if (_.isEmpty(prev)) return prev;
          const beats = removeSavingData(prev);
          beatsChanges = beats;
          return beats;
        });
        setBeatOptions((prev) => ({
          ...prev,
          rrHeatMapCellChangesState: rrHeatMapCellChanges,
          resetAppliedBulkChangesState: resetAppliedBulkChanges,
          beatChangesState: beatsChanges,
        }));
        setEcgDataMap((prev) => {
          if (_.isEqual(prev, cloneEcgDataMap)) {
            return prev;
          }
          return cloneEcgDataMap;
        });
        setReloadEcgViewer((prev) => prev + _.round(Math.random() * 100));
      });
    } catch (error) {
      logError('Failed to reload beat', error);
    }
  };

  const fetchEventsCount = async () => {
    try {
      const eventsCountFilter = {
        studyId,
        profileId,
      };
      const promises = [
        fetchHolterBeatEventsCount(eventsCountFilter, false, null, false),
        fetchHolterRhythmEventsCount(eventsCountFilter, false, null, false),
      ];
      const [holterBeatEventsCount, holterRhythmEventsCount] = await Promise.all(promises);
      setHolterBeatEventsCount(holterBeatEventsCount);
      setHolterRhythmEventsCount(holterRhythmEventsCount);
    } catch (error) {
      logError('Failed to fetch holter rhythm events count: ', error);
    }
  };

  const batchUpdateData = async () => {
    try {
      await clearApolloCache();
      await clearCachesBeatHourly();
      if (isActiveTab) {
        setIsRenderViewerEcg(false);
      }
      const promise = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.EVENT) {
          promise.push(handleReloadEvent(x.msg));
          promise.push(fetchEventsCount());
        }
      });
      const beatPromises = [];
      updateDataMessageQueue.current.forEach((x) => {
        if (x.type === AI_COMMAND.BEAT) {
          beatPromises.push(handleReloadBeat(x.msg));
        }
      });
      await Promise.all(beatPromises); // Wait for all beat promises to resolve
      await Promise.all(promise); // Wait for all promises to resolve
      promiseUpdateData.current.forEach((update) => update());
    } catch (error) {
      logError('Error: ', error);
    } finally {
      console.log('[beatHrRecoilDataEffect]-COMMANDEXECUTED-2', {
        updateDataMessageQueue: updateDataMessageQueue.current,
        promiseUpdateData: promiseUpdateData.current,
      });
      updateDataMessageQueue.current.length = 0;
      promiseUpdateData.current.length = 0;
      commandPendingQueue.current.length = 0;
      emitter.emit(EMITTER_CONSTANTS.RELOAD_EVENT_STRIP);
      if (isActiveTab) {
        setDoneReset(true);
      }
    }
  };

  const updateEventOutOfPending = _.debounce(async () => {
    await clearApolloCache();
    setIsRenderViewerEcg(false);
    setTimeout(() => {
      setIsRenderViewerEcg(true);
    }, 500);
  }, 2000);

  useEffect(() => {
    handleFetchRrOverview(true);
  }, []);

  useEffect(() => {
    if (originalDailySummaries?.length) {
      const dailySummariesCombine = [];
      for (let i = 0; i < originalDailySummaries.length; i += 1) {
        dailySummariesCombine.push({
          ...originalDailySummaries[i],
          ...(updatedDailySummaries.find((x) => x.date === originalDailySummaries[i].date)),
        });
      }
      setDailySummariesCombine(dailySummariesCombine);
    }
  }, [originalDailySummaries, updatedDailySummaries]);

  useEffect(() => {
    if (doneReset && doneSetListOriginReviewedCells) {
      setTimeout(() => {
        emitter.emit(EMITTER_CONSTANTS.AI_LOADING, {
          tab: 'beatHr',
          isLoading: false,
          isExcuted: isExcutedRef.current,
        });
        setDoneReset(false);
        if (isExcutedRef.current) {
          isExcutedRef.current = false;
        }
      }, 2000);
    }
  }, [doneReset, doneSetListOriginReviewedCells]);

  useEmitter(EMITTER_CONSTANTS.UPDATE_SET_LIST_ORIGIN_REVIEWED_CELLS_STATUS, (msg) => {
    setDoneSetListOriginReviewedCells(msg);
  }, []);

  useEmitter(EMITTER_CONSTANTS.RR_CELL_REVIEWED, () => {
    handleFetchRrOverview();
  }, []);

  useEmitter(EMITTER_CONSTANTS.RR_HEATMAP_UPDATED, () => {
    handleReloadRrHeatMap();
  }, [
    activeButton,
    studyId,
    profileId,
  ]);

  useEmitter(EMITTER_CONSTANTS.EVENTSUPDATED_EVENT, (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.EVENT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        Object.keys(msg).forEach((key) => {
          if (foundMsg.msg[key]) {
            foundMsg.msg[key] = foundMsg.msg[key].concat(msg[key]);
          } else {
            foundMsg.msg[key] = msg[key];
          }
        });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.EVENT,
        msg: _.cloneDeep(msg),
      });
    }
    if (commandPendingQueue.current.length === 0) { // update out of pending command
      updateEventOutOfPending();
    }
  }, []);

  useEmitter(EMITTER_CONSTANTS.BEATSUPDATED_EVENT, (msg) => {
    const foundMsg = updateDataMessageQueue.current.find((x) => x.type === AI_COMMAND.BEAT);
    if (foundMsg) {
      if (!_.isEmpty(msg)) {
        _.assign(foundMsg, { msg });
      }
    } else {
      updateDataMessageQueue.current.push({
        type: AI_COMMAND.BEAT,
        msg,
      });
    }
  }, []);

  useEmitter(EMITTER_CONSTANTS.DAILY_SUMMARY_UPDATED, (msg) => {
    setOriginalDailySummaries((prev) => {
      if (msg) {
        const cloneDailySummaries = _.cloneDeep(prev);
        _.forEach(msg, (dailySummary) => {
          const foundDailySummary = _.find(cloneDailySummaries, (x) => x.date === dailySummary.date);
          if (foundDailySummary) {
            _.assign(foundDailySummary, dailySummary);
          }
        });
        return cloneDailySummaries;
      }
      return prev;
    });
    setUpdatedDailySummaries([]);
  }, []);

  useEmitter(EMITTER_CONSTANTS.AFIB_HR_SUMMARY_UPDATED, (msg) => {
    const { afibAvgHr } = msg;
    setProfileAfibAvgHr(afibAvgHr);
  }, []);

  useEmitter(EMITTER_CONSTANTS.AI_PROCESS_SAVED, async (msg) => {
    await batchUpdateData();
    setIsNotReadyAfterSaveTab1(false);
  }, [selectedDateValue, activeButton, studyId, profileId, isActiveTab]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_PENDING, (msg) => {
    // *: Khi 1 user save, BE gửi command pending về tuỳ theo số lượng api gọi lúc save, push command vào mảng và khi
    // có socket command execute thì remove => khi mảng về 0 thì get hết data nhận đc trong mảng updateDataMessage => update UI
    if (msg.messageId !== profileId) {
      return;
    }

    emitter.emit(EMITTER_CONSTANTS.AI_LOADING, {
      tab: 'beatHr',
      isLoading: true,
    });
    commandPendingQueue.current.push(msg.command);
  }, [profileId]);

  useEmitter(EMITTER_CONSTANTS.COMMAND_EXECUTED, async (msg) => {
    // msg.command: update-events, update-beats, updateHolterHrDailySummary,reviewRrIntervals,get-single-events
    // updateHolterProfile, generate-report-comments
    if (msg.messageId !== profileId) return;
    if (msg.command === 'updateHolterProfile' || msg.command === 'generate-report-comments') return;
    console.log('[beatHrRecoilDataEffect]-COMMANDEXECUTED-BEFORE', {
      msg,
      commandPendingQueue: commandPendingQueue.current,
      updateDataMessageQueue: updateDataMessageQueue.current,
    });
    const foundIndexCommand = commandPendingQueue.current.findIndex((command) => command === msg.command);
    if (foundIndexCommand !== -1) {
      commandPendingQueue.current.splice(foundIndexCommand, 1);
    }
    // *: Finish all command
    if (commandPendingQueue.current.length === 0) {
      isExcutedRef.current = true;
      if (isActiveTab) {
        if (updateDataMessageQueue.current.length !== 0) {
          // *: Announce this tab have data to update
          emitter.emit(EMITTER_CONSTANTS.AI_UPDATE_TAB, '1');
          const { events, strips } = await handleCheckSavingAiProcess({
            studyId,
            profileId,
          });
          if (!events) {
            setIsNotReadyAfterSaveTab2(true);
          }
          if (!strips) {
            setIsNotReadyAfterSaveTab3(true);
          }
          await batchUpdateData();
        } else {
          setDoneReset(true);
        }
      } else {
        await batchUpdateData();
      }
    }
  }, [selectedDateValue, activeButton, isActiveTab, studyId, profileId]);

  return null;
};

export default BeatHrRecoilDataEffect;
/* eslint-disable class-methods-use-this */
/* eslint no-console:0 */
// import logHandler from './logHandler';
import { Auth } from '@aws-amplify/auth';
import _ from 'lodash';
import io from 'socket.io-client';
import { EMITTER_CONSTANTS } from '../ConstantsV2';
import AppConstant from '../ConstantsV2/appFlowActions';
import { logError } from '../LayoutV2/Reports/AiEditReport/handler';
import CONFIG from '../config/config';
import auth from './auth';
import emitter from './eventEmitter';

class SocketClient {
  constructor() {
    this.isConnected = false;
    this.isLazyLoading = false;
    this.rooms = [];
    this.intervalRoom = null;

    this.queueECGEvent = [];
    this.queueNewEvent = [];
    this.queueReportUpdate = [];

    this.roomUsersEvent = [];
    this.timeOutRoomEvent = undefined;
    this.intervalJoinRoomEvent = null;
    this.queueRoomEvent = [];

    this.roomUsersReport = [];
    this.timeOutRoomReport = undefined;
    this.intervalJoinRoomReport = null;
    this.queueRoomReport = [];

    this.timeOutOverviewtUpdate = undefined;
    this.queueOverviewUpdate = [];
  }

  getAuth = async () => {
    const accessToken = auth.isLoginWithMicrosoftAccount()
      ? (await Auth.currentSession()).getAccessToken().getJwtToken()
      : auth.token();
    auth.setOriginalToken(accessToken);
    return {
      accessToken,
    };
  };

  connectToServer = async () => {
    try {
      if (!this.socket) {
        this.socket = io(CONFIG.SOCKET, {
          forceNew: true,
          transports: ['websocket'],
          auth: async cb => cb(await this.getAuth()),
          // Prevent disconnect socket before unload to send close event to server
          closeOnBeforeunload: false,
        });
        this.socket.on('connect', this.connectListener);
      }
    } catch (error) {
      logError('Failed to connect socket: ', error);
      this.disconnectSocket();
    }
  };

  connectListener = () => {
    this.isConnected = true;
    auth.setSocketId(this.socket?.id);
    this.socket.off('reconnect');
    this.socket.on('disconnect', this.disconnectListener);
    // this.socket.on('studyEvent', this.studyEventListener);
    // this.socket.on('deviceEvent', this.deviceEventListener);
    // this.socket.on('lastSync', this.lastSyncListener);
    // this.socket.on('studyUpdated', this.studyUpdatedListener);
    // this.socket.on('studyDeleted', this.studyDeletedListener);
    // this.socket.on('inbox', this.inboxListener);
    this.socket.on('roomUsers', this.roomUsersListener);
    this.socket.on('KickClientsByToken', this.kickClientsByTokenListener);
    this.socket.on('KickClientsByUsername', this.kickClientsByUsernameListener);
    this.socket.on('newSession', this.newSessionListener);
    if (auth.isCallCenter()) {
      // this.socket.on('isPreparingFullData', this.isPreparingFullDataListener);
      // this.socket.on('newEvent', this.newEventListener);
      // this.socket.on('multipleEventsClosed', this.multipleEventsClosedListener);
      // this.socket.on('facilityUpdated', this.facilityUpdatedListener);
      // this.socket.on('bucketChanged', this.bucketChangedListener);
      // this.socket.on('moreStudies', this.moreStudiesListener);

      this.socket.on('eventUpdated', this.eventUpdatedListener);
      this.socket.on('reportUpdated', this.reportUpdatedListener);
      this.socket.on('groupUpdated', this.groupUpdatedListener);
      this.socket.on('profileReady', this.profileReadyListener);
      this.socket.on('beatsUpdated', this.beatsUpdatedListener);
      this.socket.on('eventsUpdated', this.eventsUpdatedListener);
      this.socket.on('dailySummaryUpdated', this.dailySummaryUpdatedListener);
      this.socket.on('afibHrSummaryUpdated', this.afibHrSummaryUpdatedListener);
      this.socket.on('holterProfileUpdated', this.holterProfileUpdatedListener);
      this.socket.on('technicianCommentsUpdated', this.technicianCommentsUpdatedListener);
      this.socket.on('rrCellsReviewed', this.rrCellsReviewedListener);
      this.socket.on('commandProgressUpdated', this.commandProgressUpdatedListener);
      this.socket.on('commandExecuted', this.commandExecutedListener);
      this.socket.on('commandPending', this.commandPendingListener);
      this.socket.on('rrHeatMapUpdated', this.rrHeatMapUpdatedListener);
      this.socket.on('aiProcessSaved', this.aiProcessSavedListener);
      this.socket.on('migrateAiData', this.migrateAiDataListener);
      this.socket.on('reCapturedEvents', this.reCapturedEventsListener);
    }
    //* Test socket
    // setTimeout(() => {
    //   emitter.emit(EMITTER_CONSTANTS.COMMAND_PENDING, {
    //     messageId: '65857578925735af4701e5ad',
    //     command: 'update-beats',
    //   });
    // }, 10000);
    // setTimeout(() => {
    //   emitter.emit(EMITTER_CONSTANTS.COMMAND_EXECUTED, {
    //     messageId: '65857578925735af4701e5ad',
    //     command: 'update-beats',
    //     isSuccess: true,
    //   });
    // }, 11000);
  };

  disconnectListener = (error) => {
    console.log('socket io - on disconnect:', error);

    // emitter.emit(EMITTER_CONSTANTS.LOST_CONNECTION, CONNECTION_TYPE.SOCKET);
    // alert('Sorry for the inconvenience!\nThe system ran into a problem and needs to reload a page.');
    // window.location.reload();

    this.isConnected = false;
    this.socket.io.on('reconnect', this.reconnectListener);

    this.socket.off('connect');
    this.socket.off('disconnect');

    // this.socket.off('studyEvent');
    // this.socket.off('deviceEvent');
    // this.socket.off('lastSync');
    // this.socket.off('studyUpdated');
    // this.socket.off('studyDeleted');
    // this.socket.off('inbox');
    this.socket.off('roomUsers');
    this.socket.off('KickClientsByToken');
    this.socket.off('KickClientsByUsername');
    this.socket.off('newSession');

    if (auth.isCallCenter()) {
      // this.socket.off('isPreparingFullData');
      // this.socket.off('newEvent');
      // this.socket.off('multipleEventsClosed');
      // this.socket.off('facilityUpdated');
      // this.socket.off('bucketChanged');
      // this.socket.off('moreStudies');

      this.socket.off('eventUpdated');
      this.socket.off('reportUpdated');
      this.socket.off('groupUpdated');
      this.socket.off('profileReady');
      this.socket.off('beatsUpdated');
      this.socket.off('eventsUpdated');
      this.socket.off('dailySummaryUpdated');
      this.socket.off('afibHrSummaryUpdated');
      this.socket.off('holterProfileUpdated');
      this.socket.off('technicianCommentsUpdated');
      this.socket.off('rrCellsReviewed');
      this.socket.off('commandProgressUpdated');
      this.socket.off('commandExecuted');
      this.socket.off('commandPending');
      this.socket.off('rrHeatMapUpdated');
      this.socket.off('aiProcessSaved');
      this.socket.off('migrateAiData');
    }

    if (error && error.trim() === 'io server disconnect') {
      window.isSessionExpired = true;
      emitter.emit(EMITTER_CONSTANTS.EXPIRED_TOKEN, 'request');
      this.socket = null;
    }

    // if (error && error.trim() === 'ping timeout' && !auth.token()) {
    //   this.disconnectSocket();
    //   this.socket = null;
    // }
    // if (error && error.trim() === 'io server disconnect') {
    //   emitter.emit(EMITTER_CONSTANTS.EXPIRED_TOKEN, 'request');
    //   this.socket = null;
    // }
  };

  reconnectListener = () => {
    console.log('on reconnect');
    this.socket.on('connect', this.connectListener);
    // window.location.reload();
    // Remove duplicate data
    const uniqRooms = _.uniqWith(this.rooms, _.isEqual);
    console.log('uniqRooms', uniqRooms);
    _.forEach(uniqRooms, (room) => {
      const { name, id } = room;
      switch (name) {
        case 'joinReportRoom': {
          this.sendJoinReportRoom(id);
          break;
        }
        default: {
          this.emitIntervalEvent(name, id);
          break;
        }
      }
    });
  };

  eventUpdatedListener = (msg) => {
    console.log('socket io - eventUpdatedListener', msg);
    if (msg.study?._id) {
      this.addQueueECGEventUpdate(msg.study?._id);
    }
    emitter.emit(EMITTER_CONSTANTS.UPDATE_EVENT_ECG, msg);
    if (auth.isCallCenter()) {
      this.addQueueHandleUpdateReport({ type: 'eventUpdated', data: msg });
    }
  };

  reportUpdatedListener = (msg) => {
    console.log('socket io - reportUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.REPORT_UPDATED, msg);
    if (auth.isCallCenter()) {
      this.addQueueHandleUpdateReport({ type: 'reportUpdated', data: msg });

      if (auth.isCallCenterSupervisor() || auth.isCallCenterQaLeader()) {
        this.addQueueHandleUpdateOverview({ type: 'reportUpdated', data: msg });
      }
    }
  };

  migrateAiDataListener = (msg) => {
    console.log('socket io - migrateAiDataListener', msg);
    emitter.emit(EMITTER_CONSTANTS.MIGRATE_AI_DATA_VER1_TO_VER2, msg);
  };

  newSessionListener = (msg) => {
    console.log('socket io - newSessionListener', msg);
    emitter.emit(EMITTER_CONSTANTS.NEW_SESSION, msg);
  };

  groupUpdatedListener = (msg) => {
    console.log('socket io - groupUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.GROUP_UPDATED, msg);
  };

  profileReadyListener = (msg) => {
    console.log('socket io - profileReadyListener', msg);
    emitter.emit(EMITTER_CONSTANTS.PROFILE_READY, msg);
  };

  beatsUpdatedListener = (msg) => {
    console.log('socket io - beatsUpdatedListener', msg);
    // logHandler.addLog('beatsUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.BEATSUPDATED_EVENT, msg);
  };

  eventsUpdatedListener = (msg) => {
    console.log('socket io - eventsUpdatedListener', msg);
    // logHandler.addLog('eventsUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.EVENTSUPDATED_EVENT, msg);
  };

  afibHrSummaryUpdatedListener = (msg) => {
    console.log('socket io - afibHrSummaryUpdatedListener', msg);
    // logHandler.addLog('afibHrSummaryUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.AFIB_HR_SUMMARY_UPDATED, msg);
  };

  dailySummaryUpdatedListener = (msg) => {
    console.log('socket io - dailySummaryUpdatedListener', msg);
    // logHandler.addLog('dailySummaryUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.DAILY_SUMMARY_UPDATED, msg);
  };

  holterProfileUpdatedListener = (msg) => {
    console.log('socket io - holterProfileUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.HOLTER_PROFILE_UPDATED, msg);
  };

  technicianCommentsUpdatedListener = (msg) => {
    console.log('socket io - technicianCommentsUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.TECHNICIAN_COMMENT_UPDATED, msg);
  };

  rrCellsReviewedListener = (msg) => {
    console.log('socket io - rrCellsReviewedListener', msg);
    // logHandler.addLog('rrCellsReviewed', msg);
    emitter.emit(EMITTER_CONSTANTS.RR_CELL_REVIEWED, msg);
  };

  commandProgressUpdatedListener = (msg) => {
    console.log('socket io - commandProgressUpdatedListener', msg);
    emitter.emit(EMITTER_CONSTANTS.COMMAND_PROGRESS_UPDATED, msg);
  };

  commandExecutedListener = (msg) => {
    console.log('socket io - commandExecutedListener', msg);
    // logHandler.addLog('commandExecuted', msg);
    // logHandler.sendLog();
    emitter.emit(EMITTER_CONSTANTS.COMMAND_EXECUTED, msg);
  };

  commandPendingListener = (msg) => {
    console.log('socket io - commandPendingListener', msg);
    // logHandler.addLog('commandPending', msg);
    emitter.emit(EMITTER_CONSTANTS.COMMAND_PENDING, msg);
  };

  rrHeatMapUpdatedListener = (msg) => {
    console.log('socket io - rrHeatMapUpdatedListener', msg);
    // logHandler.addLog('rrHeatMapUpdated', msg);
    emitter.emit(EMITTER_CONSTANTS.RR_HEATMAP_UPDATED, msg);
  };

  aiProcessSavedListener = (msg) => {
    console.log('socket io - aiProcessSavedListener', msg);
    // logHandler.addLog('aiProcessSaved', msg);
    // logHandler.sendLog();
    emitter.emit(EMITTER_CONSTANTS.AI_PROCESS_SAVED, msg);
  };

  reCapturedEventsListener = async (msg) => {
    console.log('socket io - reCapturedEventsListener', msg);
    emitter.emit(EMITTER_CONSTANTS.RE_CAPTURE_EVENTS, msg);
  };

  roomUsersListener = (msg) => {
    console.log('socket io - roomUsersListener', msg);
    // logHandler.addLog('roomUsers', msg);
    if (msg.roomType === 'Event') {
      this.roomUsersEvent.push(msg);
    } else if (msg.roomType === 'Report') {
      this.roomUsersReport.push(msg);
    }
    if (!this.timeOutRoomEvent) {
      this.timeOutRoomEvent = setTimeout(() => {
        if (this.roomUsersEvent.length > 0) {
          emitter.emit(EMITTER_CONSTANTS.EVENT_ROOM_USER, this.roomUsersEvent.splice(0, this.roomUsersEvent.length));
        }
        if (this.roomUsersReport.length > 0) {
          emitter.emit(EMITTER_CONSTANTS.REPORT_ROOM_USER, this.roomUsersReport.splice(0, this.roomUsersReport.length));
        }
        this.timeOutRoomEvent = undefined;
      }, 1000);
    }
  };

  kickClientsByTokenListener = (msg) => {
    console.log('socket io - kickClientsByTokenListener', msg);
    emitter.emit(AppConstant.LOGOUT_REQUEST, 'request');
  };

  kickClientsByUsernameListener = (msg) => {
    console.log('socket io - kickClientsByUsernameListener', msg);
    emitter.emit(AppConstant.LOGOUT_REQUEST, 'request');
  };

  emitIntervalEvent = (status, id) => {
    console.log('EMITEVENT', status, id, this.isConnected);
    if (this.isConnected) {
      // console.log(`${this.TAG} ${status} `, id);
      this.socket.emit(status, id);
    } else {
      const interval = setInterval(() => {
        // console.log(`${this.TAG} ${status} `, id);
        if (this.isConnected) {
          this.socket.emit(status, id);
          clearInterval(interval);
        }
        if (!auth.token()) {
          clearInterval(interval);
        }
      }, 1000);
    }
  };

  handleStoreRooms = (name, id) => {
    if (!_.some(this.rooms, x => x.id === id)) {
      this.rooms.push({ name, id });
    }
  };

  emitRoom = (id) => {
    if (id && id !== 'undefined') {
      this.handleStoreRooms('room', id);
      this.emitIntervalEvent('room', id);
    }
  };

  addQueueECGEventUpdate = (studyId, msg = {}) => {
    this.queueECGEvent.push(studyId);
    if (!_.isEmpty(msg)) {
      this.queueNewEvent.push({ id: msg.id, stripImgs: msg.stripImgs });
    }
    if (!this.timeOutEventUpdate) {
      this.timeOutEventUpdate = setTimeout(() => {
        this.timeOutEventUpdate = undefined;
        emitter.emit(EMITTER_CONSTANTS.UPDATE_TOTAL_EVENTS, this.queueECGEvent.splice(0, this.queueECGEvent.length));
        if (this.queueNewEvent.length > 0) {
          emitter.emit(EMITTER_CONSTANTS.UPDATE_NEW_EVENT_ECG, this.queueNewEvent.splice(0, this.queueNewEvent.length));
        }
      }, 5000);
    }
  };

  addQueueHandleUpdateReport = (msg) => {
    this.queueReportUpdate.push(msg);
    if (!this.timeOutReportUpdate) {
      this.timeOutReportUpdate = setTimeout(() => {
        this.timeOutReportUpdate = undefined;
        if (this.updateReportReminder) {
          console.log('this.queueReportUpdate', this.queueReportUpdate);
          this.updateReportReminder(this.queueReportUpdate.splice(0, this.queueReportUpdate.length));
        }
      }, 1000);
    }
  };

  addQueueHandleUpdateOverview = (msg) => {
    this.queueOverviewUpdate.push(msg);
    if (!this.timeOutOverviewtUpdate) {
      this.timeOutOverviewtUpdate = setTimeout(() => {
        this.timeOutOverviewtUpdate = undefined;
        emitter.emit(EMITTER_CONSTANTS.UPDATE_OVERVIEW, this.queueOverviewUpdate.splice(0, this.queueOverviewUpdate.length));
      }, 15000);
    }
  };

  sendMessageToServer(event, data) {
    console.log('sendMessageToServer ', event, data);
    this.socket.emit(event, data);
  }

  // send join event room
  sendJoinEventRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    this.queueRoomEvent.push(msg);
    if (this.isConnected) {
      this.socket.emit('joinEventRoom', msg);
    } else if (!this.intervalJoinRoomEvent) {
      this.intervalJoinRoomEvent = setInterval(() => {
        if (this.isConnected) {
          const datas = _.assign([], this.queueRoomEvent);
          this.queueRoomEvent.splice(0, datas.length);
          _.forEach(datas, (e) => {
            this.socket.emit('joinEventRoom', e);
          });
          clearInterval(this.intervalJoinRoomEvent);
          this.intervalJoinRoomEvent = null;
        }
      }, 1000);
    }
  }

  // send join report room
  sendJoinReportRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    this.queueRoomReport.push(msg);
    if (this.isConnected) {
      console.log('[ ==> ] sendJoinReportRoom connected', msg);
      this.handleStoreRooms('joinReportRoom', msg.room);
      this.socket.emit('joinReportRoom', msg);
    } else if (!this.intervalJoinRoomReport) {
      this.intervalJoinRoomReport = setInterval(() => {
        if (this.isConnected) {
          const datas = _.assign([], this.queueRoomReport);
          this.queueRoomReport.splice(0, datas.length);
          // Remove duplicate data
          const uniqDatas = _.uniqWith(datas, _.isEqual);
          _.forEach(uniqDatas, (e) => {
            console.log('[ ==> ] sendJoinReportRoom', e);
            this.handleStoreRooms('joinReportRoom', e.room);
            this.socket.emit('joinReportRoom', e);
          });
          clearInterval(this.intervalJoinRoomReport);
          this.intervalJoinRoomReport = null;
        }
      }, 1000);
    }
  }

  sendLeaveReportRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    // *: Only use interval for emiting room
    // this.emitIntervalEvent('leaveReportRoom', msg);
    if (this.socket && this.isConnected) {
      console.log('[ ==> ] sendLeaveReportRoom', msg);
      _.remove(this.rooms, x => x.id === msg.room);
      this.socket.emit('leaveReportRoom', msg);
    }
  }

  sendLeaveEventRoom(room, isPreview = false) {
    const msg = {
      room,
      isPreview,
    };
    if (this.socket && this.isConnected) {
      _.remove(this.rooms, x => x.id === msg.room);
      this.socket.emit('leaveEventRoom', msg);
    }
  }

  disconnectSocket() {
    console.log('socket io disconnect', this.socket);
    if (this.socket) {
      this.socket.disconnect();
    }
    this.socket = null;
    this.rooms.length = 0;
  }
}

const staticSocket = new SocketClient();

export default staticSocket;
<script> 
$( document ).ready(function() {  
  
	//Change this ID's for the ID's of the pages you'd like to exclude.
	var exclude = ["d295a5b5-9761-4e54-a776-76fcbcafdd7e", 
                       "582eee08-77a6-4038-8e92-8c356f1bb64b", 
                       "dcd9aed3-ca05-4f9c-9fb9-4f09b44246e7"]; 
   
  	//Get page id.
	var pageId = window.ub.page.id
  	//Compare pageId to array
  	if (jQuery.inArray(pageId, exclude)=='-1') {
      
    		//ADD YOUR SCRIPT HERE
      
        }
});
</script>
////////////////**** FILTER FUNCTION*****///////////////////
const MyNum = [1,2,3,4,5,6,7,8,9,10]
   
   
   
const  mynums = MyNum
                .map((num) => num  * 10)
                .map((num) => num  + 1)
                .filter((num) => num  >= 40)
                
console.log(mynums);
                
//////// reduce function ///////////////////////
                
const NUM = [1, 2, 3, 4];
const mytotal = NUM.reduce(function (acc, currval) {
    console.log(`acc: ${acc} and currval: ${currval}`);
    return acc + currval;
}, 0); // zero is the acc's initial value
console.log(mytotal);

const mytot = NUM.reduce((acc, curr) => acc+curr, 0 )
console.log(mytot);

const shoppingCart = [
    {
        itemName: "js course",
        price: 2999
    },
    {
        itemName: "py course",
        price: 999
    },
    {
        itemName: "mobile dev course",
        price: 5999
    },
    {
        itemName: "data science course",
        price: 12999
    },
]

const priceToPay = shoppingCart.reduce((acc, item) => acc + item.price, 0)

console.log(priceToPay);
    $cnpp = cnplanpriceTable::getOneByPlan('A_PP_FREE1');

    $ads = cnadTable::getInstance()
      ->createQuery()
      ->andWhere('userid = ?', 1107924)
      ->andWhere('hw_pay_plan LIKE ?', '%A_PA_FREE1%')
      ->execute([], Doctrine::HYDRATE_ON_DEMAND);
    $this->log('Found ' . count($ads) . ' ads');

    foreach ( $ads as $cnad )
    {
      $cnad->setPlan($cnpp);
      $cnad->save();

      $cnexp = cnexpirationTable::getItem($cnad, 'ad_plan');
      $cnexp->setValue('A_PP_FREE1');
      $cnexp->save();
      $this->log('Processed ' . $cnad->getLinkId());
    }
const getWeekOfYear = (date: Date): number => {
  const startOfYear = new Date(date.getFullYear(), 0, 1);
  const days = Math.floor(
    (date.getTime() - startOfYear.getTime()) / (24 * 60 * 60 * 1000)
  );
  return Math.ceil((days + startOfYear.getDay() + 1) / 7);
};
///////////***********FILTER , MAP AND REDUCE ********////////////

 const coding = ["js", "ruby", "java", "python", "cpp"]


 const values = coding.forEach( (item) => {
   console.log(item);
     return item
 } )

 console.log(values);

/////////////////*********** FILTER FUNCTION **********************////////////
const myNums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// const newNums = myNums.filter( (num) => {
//  return num > 4
// } )

const newNums = []

 myNums.forEach( (num) => {
     if (num > 4) {
         newNums.push(num)
    }
 } )

console.log(newNums);


const books = [
    { title: 'Book One', genre: 'Fiction', publish: 1981, edition: 2004 },
    { title: 'Book Two', genre: 'Non-Fiction', publish: 1992, edition: 2008 },
    { title: 'Book Three', genre: 'History', publish: 1999, edition: 2007 },
    { title: 'Book Four', genre: 'Non-Fiction', publish: 1989, edition: 2010 },
    { title: 'Book Five', genre: 'Science', publish: 2009, edition: 2014 },
    { title: 'Book Six', genre: 'Fiction', publish: 1987, edition: 2010 },
    { title: 'Book Seven', genre: 'History', publish: 1986, edition: 1996 },
    { title: 'Book Eight', genre: 'Science', publish: 2011, edition: 2016 },
    { title: 'Book Nine', genre: 'Non-Fiction', publish: 1981, edition: 1989 },
  ];

  let userBooks  = books.filter( (bk) => bk.genre === 'History')
  console.log(userBooks);
  
  userBook = books.filter( (bk) => { 
    return bk.publish >= 1995 && bk.genre === "History"
})
  console.log(userBook);
star

Sat Nov 30 2024 23:00:58 GMT+0000 (Coordinated Universal Time)

@MinaTimo

star

Sat Nov 30 2024 22:34:51 GMT+0000 (Coordinated Universal Time)

@MinaTimo

star

Sat Nov 30 2024 18:27:19 GMT+0000 (Coordinated Universal Time)

@emily00

star

Sat Nov 30 2024 14:52:14 GMT+0000 (Coordinated Universal Time) https://catalog.viva-scim.ro/

@676rhfrff #c# #c++ #nodejs

star

Sat Nov 30 2024 14:24:13 GMT+0000 (Coordinated Universal Time)

@mehran

star

Sat Nov 30 2024 14:23:05 GMT+0000 (Coordinated Universal Time)

@mehran

star

Sat Nov 30 2024 14:22:39 GMT+0000 (Coordinated Universal Time)

@mehran

star

Sat Nov 30 2024 10:06:55 GMT+0000 (Coordinated Universal Time) https://www.techwithtim.net/tutorials/game-development-with-python/pygame-tutorial/projectiles

@Alishure

star

Fri Nov 29 2024 23:11:47 GMT+0000 (Coordinated Universal Time) https://www.notion.so/lostmytop/Sister-Sister-10d02d4a0567807599d1cb072da03824

@CallTheCops ##stories ##en ##nsfw ##docs

star

Fri Nov 29 2024 21:56:33 GMT+0000 (Coordinated Universal Time)

@nofil

star

Fri Nov 29 2024 21:25:48 GMT+0000 (Coordinated Universal Time)

@gbritgs

star

Fri Nov 29 2024 18:53:42 GMT+0000 (Coordinated Universal Time)

@Joe_Devs #php

star

Fri Nov 29 2024 16:38:45 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:37:18 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:35:52 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:33:19 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:31:06 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:29:26 GMT+0000 (Coordinated Universal Time) https://github.com/Asadullah109/sigma-togather

@asadiftekhar10

star

Fri Nov 29 2024 16:29:17 GMT+0000 (Coordinated Universal Time) https://github.com/Asadullah109/sigma-togather

@asadiftekhar10

star

Fri Nov 29 2024 16:26:49 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 16:24:36 GMT+0000 (Coordinated Universal Time)

@Asad_ullah

star

Fri Nov 29 2024 07:26:55 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 07:07:40 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 07:05:10 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 06:51:49 GMT+0000 (Coordinated Universal Time)

@pcube312

star

Fri Nov 29 2024 06:37:13 GMT+0000 (Coordinated Universal Time) https://www.google.com/search?q

@zipik

star

Fri Nov 29 2024 06:36:25 GMT+0000 (Coordinated Universal Time) https://www.google.com/search?q

@zipik

star

Fri Nov 29 2024 06:28:52 GMT+0000 (Coordinated Universal Time) https://miracle-garden.live/

@zipik

star

Thu Nov 28 2024 19:48:52 GMT+0000 (Coordinated Universal Time) vir pelo tik tok

@shaolin #javascript

star

Thu Nov 28 2024 15:40:56 GMT+0000 (Coordinated Universal Time)

@usman13

star

Thu Nov 28 2024 15:38:31 GMT+0000 (Coordinated Universal Time)

@RehmatAli2024 #deluge

star

Thu Nov 28 2024 15:27:23 GMT+0000 (Coordinated Universal Time)

@anamarie

star

Thu Nov 28 2024 13:45:55 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Thu Nov 28 2024 13:35:57 GMT+0000 (Coordinated Universal Time) https://creatiosoft.com/texas-holdem-poker-game-development-company

@Rishabh ##texasholdem ##pokersoftware

star

Thu Nov 28 2024 12:56:53 GMT+0000 (Coordinated Universal Time)

@odesign

star

Thu Nov 28 2024 12:44:23 GMT+0000 (Coordinated Universal Time) לא בבית כרגע אבל אני יתאר. תאורת מפתח בצד שמאל (בתמונה שלי זה הצד הימני של הפנים) של אפטור 200 וואט עם סופט בוקס בגודל של 60 ס״מ וגריד(רציתי בגודל 80 אבל יש לי מגבלה של מקום). תאורה משלימה בצד ימין (זה הצללית הקלה בצד שמאל של הפנים שלי בתמונה) של פנס לד שניתן לעמעום עם טווח של 3000- 5600 קלווין. הגדרות המצלמה - אורך מוקד מוגדר על 67, איזו על 100 ומהירות תריס 1/300 אם אני לא טועה, איזון הלבן 4800 (למרות שבמצלמה מקצועית היה נכון יותר להגדיר 5600, בבריו זה לא מדויק בעליל). תאורה אחורית חמה ויש עוד אחת בצבעי rgb שלא מופיעה בצילום

@odesign

star

Thu Nov 28 2024 10:44:22 GMT+0000 (Coordinated Universal Time) JIBAZM1u

@odesign

star

Thu Nov 28 2024 09:48:29 GMT+0000 (Coordinated Universal Time) https://algoji.com/apibridge-python-sample-code/

@pk20

star

Thu Nov 28 2024 08:14:15 GMT+0000 (Coordinated Universal Time)

@hamzahanif192

star

Thu Nov 28 2024 02:30:32 GMT+0000 (Coordinated Universal Time) /Users/khainguyen/ITRVN_REPO/BTCY/btcy-bioflux-frontend-ai_report_processing/app/LayoutV2/Reports/AiEditReport/RhythmEvents/recoil/rhythmEventsRecoilDataEffect.js

@khainguyenhm

star

Thu Nov 28 2024 02:28:57 GMT+0000 (Coordinated Universal Time) /Users/khainguyen/ITRVN_REPO/BTCY/btcy-bioflux-frontend-ai_report_processing/app/LayoutV2/Reports/AiEditReport/BeatHR/recoil/beatHrRecoilDataEffect.js

@khainguyenhm

star

Thu Nov 28 2024 02:27:42 GMT+0000 (Coordinated Universal Time)

@khainguyenhm

star

Thu Nov 28 2024 01:48:36 GMT+0000 (Coordinated Universal Time) https://gist.github.com/victorzen/c5aae1a5880fe2be79a92776ee040d7a

@D_Unbounce

star

Wed Nov 27 2024 21:26:25 GMT+0000 (Coordinated Universal Time)

@E23CSEU1151

star

Wed Nov 27 2024 20:55:24 GMT+0000 (Coordinated Universal Time)

@nachopascual #php

star

Wed Nov 27 2024 20:37:53 GMT+0000 (Coordinated Universal Time)

@desiboli #javascript #typescript

star

Wed Nov 27 2024 20:26:06 GMT+0000 (Coordinated Universal Time)

@E23CSEU1151

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension