QT-模拟电梯上下楼

QT-模拟电梯上下楼

  • 一、演示效果
  • 二、核心程序
  • 三、下载链接


一、演示效果

在这里插入图片描述

二、核心程序

#include "ElevatorController.h"
#include <QGridLayout>
#include <QLabel>
#include <QGroupBox>
#include <QGridLayout>
#include <QPushButton>
#include <QDebug>
#include <QChar>
#include <QGuiApplication>
#include <QScreen>
#include <queue>

ElevatorController::ElevatorController(Ui::MainWindow* u, int numElevators, int numFloors)
{
    // create/populate ui ComboBox elements
    ui = u;
    QStringList evs;
    for (int elevator = 1; elevator <= numElevators; ++elevator)
    {
        evs << QString("Elevator: %1").arg(elevator);
    }
    ui->comboElevatorBox->addItems(evs);
    connect(ui->comboElevatorBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &ElevatorController::elevatorSelected);

    evs.clear();

    for (int floorc = 1; floorc <= numFloors; ++floorc)
    {
        evs << QString("Floor: %1").arg(floorc);
    }
    ui->comboFloorBox->addItems(evs);

    // buttons connected
    connect(ui->pushElevatorButton, &QPushButton::clicked, this, &ElevatorController::buttonElevatorSubmit);
    connect(ui->pushHelpButton, &QPushButton::clicked, this, &ElevatorController::buttonElevatorHelp);
    connect(ui->pushPlaceButton, &QPushButton::clicked, this, &ElevatorController::buttonPlaceOnFloor);
    connect(ui->pushMoveButton, &QPushButton::clicked, this, &ElevatorController::buttonMoveToElevator);
    connect(ui->pushAdd10FloorButton, &QPushButton::clicked, this, &ElevatorController::add10ToEachFloor);
    connect(ui->pushBuildingEmergencyButton, &QPushButton::clicked, this, &ElevatorController::triggerBuildingEmergency);
    connect(ui->pushEmergencyResetAllButton, &QPushButton::clicked, this, &ElevatorController::resetAllElevatorsEmergency);
    connect(ui->pushLeaveButton, &QPushButton::clicked, this, &ElevatorController::buttonLeaveElevator);

    // spin box buttons:
    connect(ui->spinBoxMove, qOverload<int>(&QSpinBox::valueChanged), this, &ElevatorController::moveComboBoxChange);
    connect(ui->spinBoxLeaveElevator, qOverload<int>(&QSpinBox::valueChanged), this, &ElevatorController::moveLeaveElevatorBoxChange);

    // combo box change:
    connect(ui->comboFloorBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &ElevatorController::floorSelected);

    // keep in mind: "setWidget" and "setLayout" etc add to the ui tree, memory managed by Qt not Me :-)

    // widget to hold the grid layout
    QWidget* elevatorWidget = new QWidget();
    ui->elevatorScrollArea->setWidget(elevatorWidget); // Set the content widget of the ElevatorController

    // QGridLayout* elevatorGridLayout
    elevatorGridLayout = new QGridLayout(elevatorWidget);
    elevatorWidget->setLayout(elevatorGridLayout);



    // Add buttons or labels to the grid layout based on dimensions
    for (int floor = numFloors - 1; floor >= 0; floor--)
    {
        for (int elevator = 1; elevator <= numElevators; ++elevator)
        {
            // Create a QLabel for each position
            QLabel* cube = new QLabel;
            cube->setText(" ");
            cube->setFixedSize(CUBE_SIZE, CUBE_SIZE);
            QString color = "gray";

            if(numFloors - floor - 1 == 0) // all ev's start at 0
                color = "red";

            cube->setStyleSheet(QString("background-color: %1").arg(color));

            // Add the widget to the grid layout at the specified position
            elevatorGridLayout->addWidget(cube, floor, elevator);
        }

        Floor* flr = new Floor(floor + 1); // floor class is a part of the UI

        // Connect the signals from the Floor to the slots in the ElevatorController
        connect(flr, &Floor::upButtonPressed, this, &ElevatorController::buttonPressedUp);
        connect(flr, &Floor::downButtonPressed, this, &ElevatorController::buttonPressedDown);

        // adds the floor at the start (far left)
        elevatorGridLayout->addWidget(flr, numFloors - floor - 1, 0);
        floors.push_back(flr);
    }

    // create elevators
    for (int elevator = 1; elevator <= numElevators; ++elevator)
    {
        Elevator* ev = new Elevator(elevator);
        elevators.push_back(ev);
        updateDisplays();
        // should be connecting slot in elevator to signals in elevator controller
        connect(this, &ElevatorController::resetEmergency, ev, &Elevator::resetEmergencyInElevator);
        connect(this, &ElevatorController::sendRequestToElevator, ev, &Elevator::pressButton);
        connect(this, &ElevatorController::helpButton, ev, &Elevator::helpButtonPressed);
        connect(this, &ElevatorController::moveElevatorToFloor, ev, &Elevator::moveTofloor);
        connect(this, &ElevatorController::removeElevatorPassengers, ev, &Elevator::removePassengers);
        connect(this, &ElevatorController::addElevatorPassengers, ev, &Elevator::addPassengers);
        connect(this, &ElevatorController::buildingEmergency, ev, &Elevator::emergency);
        connect(this, &ElevatorController::pressButton, ev, &Elevator::pressButton);
        connect(this, &ElevatorController::unpressButton, ev, &Elevator::unpressButton);
        connect(ev, &Elevator::floorChanged, this, &ElevatorController::elevatorFloorChanged);
        connect(ev, &Elevator::doorOpened, this, &ElevatorController::doorOpened);
        connect(ev, &Elevator::doorClosed, this, &ElevatorController::doorClosed);
        connect(ev, &Elevator::doorBlocked, this, &ElevatorController::doorBlocked);
        connect(ev, &Elevator::overloaded, this, &ElevatorController::overloaded);
        connect(ev, &Elevator::emergencyOnBoard, this, &ElevatorController::emergency);
        connect(ev, &Elevator::updateDisplays, this, &ElevatorController::updateDisplays);

        QThread* evThread = new QThread;
        ev->moveToThread(evThread);
        evThread->start();
        threads.push_back(evThread);
    }

    requestScanTimer = new QTimer(this);
    connect(requestScanTimer, &QTimer::timeout, this, &ElevatorController::scanRequestTree);
    requestScanTimer->start(SCAN_REQUEST_TREE_SECS);  // Scan backup request tree every 15 seconds, in case overflow

    qDebug() << "Elevator Controller Initialized";
}

ElevatorController::~ElevatorController() // clean up floors
{
    for(int i = 0; i < floors.size(); i++)
        delete floors[i];

    requestScanTimer->stop();
    delete requestScanTimer;

    for(int i = 0; i < threads.size(); i++)
    {
        threads[i]->quit();
        threads[i]->wait();
        delete threads[i];
    }
}

// --- UI INPUT & CALLBACK FUNCS ---


void ElevatorController::handleScreenResized(int w, int h)
{
    int bufferGap = 10;
    ui->elevatorScrollArea->resize(w - ui->InputTerminal->width() - 3*bufferGap, h - bufferGap*6);
    qDebug() << "Reinit scale -- uiWidth: " << w << " uiHeight: " << h;

    ui->InputTerminal->move(ui->elevatorScrollArea->x() + w - ui->InputTerminal->width() - 2*bufferGap, ui->InputTerminal->y());
    ui->InputTerminal->resize(ui->InputTerminal->width(), h - bufferGap*5);
}

void ElevatorController::updateDisplays()
{
    int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt(); // stored from 0


    QString buttonList = "";
    const std::set<int>& blist = elevators[ev - 1]->getButtonsPressed();
    for(const int& a : blist)
    {
        buttonList += QString::number(a) + " ";
    }
    ui->textBrowserButtonsPressed->setPlainText(buttonList);

    const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();
    ui->passengerOnFloorNumber->display(floors[flr - 1]->peopleOnFloor());
    ui->passengerNumber->display(elevators[ev - 1]->numPassengers());
}

void ElevatorController::buttonElevatorSubmit()
{
    // get the int values from the combo boxes
    int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt();
    int fb = ui->comboFloorBox->currentText().remove(0, 7).toInt();

    qDebug() << "BUTTON - elevator submit pressed elev: " << ev << " floor button: " << fb;

    if(elevators[ev - 1]->getButtonsPressed().count(fb) > 0)
        emit unpressButton(ev, fb);
    else
        emit pressButton(ev, fb);
}

void ElevatorController::buttonPlaceOnFloor()
{
    qDebug() << "BUTTON buttonPlaceOnFloor.... spawning ppl on floor";

    const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt() - 1;

    floors[flr]->addPeople(ui->spinBoxPlace->value());
    ui->passengerOnFloorNumber->display(floors[flr]->peopleOnFloor());

    ui->spinBoxPlace->setValue(0);
}

void ElevatorController::buttonMoveToElevator()
{
    qDebug() << "BUTTON: buttonMoveToElevator.... moving ppl ";

    const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();
    int evweak = ui->comboElevatorBox->currentText().remove(0, 10).toInt() - 1; // if this is on the same floor its used

    Elevator* availableEv = nullptr;
    Elevator* weakEv = nullptr;
    bool potentialEvPassed = false;

    if(elevators[evweak]->currentFloor() == flr) // soft lock the current elevator
        weakEv = elevators[evweak];

    for(Elevator* ev : elevators) // unless theres one that makes more sense
    {
        if(ev->currentFloor() == flr && ev->currentState() == Elevator::DoorsOpen)
        {
            availableEv = ev;
            if(weakEv == ev && weakEv != nullptr)
            {
                availableEv = weakEv;
                break;
            }
        }
    }

    if(!availableEv)
        return;

    const int val = ui->spinBoxMove->value(); //usr input
    ui->spinBoxMove->setValue(0);

    floors[flr - 1]->removePeople(val);
    //    emit addElevatorPassengers(availableEv->getId(), flr, val);
    elevators[availableEv->getId() - 1]->addPassengers(availableEv->getId(), flr, val);
    // just set the combo box option to the one that people were put into automatically... for visibility
    ui->comboElevatorBox->setCurrentIndex(availableEv->getId() - 1);

    // update the floor on people display
    updateDisplays();
}

void ElevatorController::buttonLeaveElevator()
{

    int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt();

    qDebug() << "BUTTON: buttonLeaveElevator.... moving ppl EV: " << ev << " FLR: " << elevators[ev - 1]->currentFloor();


    const int val = ui->spinBoxLeaveElevator->value(); //usr input
    ui->spinBoxLeaveElevator->setValue(0);

    emit removeElevatorPassengers(elevators[ev - 1]->getId(), elevators[ev - 1]->currentFloor(), val);
    floors[elevators[ev - 1]->currentFloor() - 1]->addPeople(val);

    // just set the combo box option to the one that people were put into automatically... for visibility
    ui->comboFloorBox->setCurrentIndex(elevators[ev - 1]->currentFloor() - 1);
    ui->passengerNumber->display(elevators[ev-1]->numPassengers());
    updateDisplays();

    const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();
    if(elevators[ev - 1]->currentFloor() != flr)
        return;

    // update the floor on people display
    ui->passengerOnFloorNumber->display(floors[elevators[ev - 1]->currentFloor()]->peopleOnFloor());
    updateDisplays();

    controlMoveButtonActivated();
}


void ElevatorController::add10ToEachFloor()
{
    qDebug() << "BUTTON add 10 To Each Floor.... spawning 10 ppl on each floor!";

    for(Floor* f : floors)
    {
        f->addPeople(10);
    }

    const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt() - 1;
    ui->passengerOnFloorNumber->display(floors[flr]->peopleOnFloor());
    ui->spinBoxPlace->setValue(0);
}

void ElevatorController::triggerBuildingEmergency()
{
    emit buildingEmergency(-1);
}

void ElevatorController::buttonElevatorHelp()
{
    int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt();
    emit helpButton(ev);
    updateDisplays();
}

void ElevatorController::resetAllElevatorsEmergency()
{
    emit resetEmergency(-1);
    updateDisplays();
}

void ElevatorController::controlMoveButtonActivated(Elevator* availableEv)
{
    // we want to check if there is an elevator on the floor in door open state
    // & set the control button to active or not based on it
    //qDebug() << "BUTTON ACTIVATE: Activating/Deactivating the Move Button to allow moving ppl ";

    const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();
    const int evNum = ui->comboElevatorBox->currentText().remove(0, 10).toInt();

    for(Elevator* ev : elevators)
    {
        if(availableEv != nullptr)
            break;
        if(ev->currentFloor() == flr && ev->currentState() == Elevator::DoorsOpen || elevators[evNum - 1]->currentState() == Elevator::Overload)
            availableEv = ev;
    }

    if(elevators[evNum - 1]->currentState() == Elevator::DoorsOpen || elevators[evNum - 1]->currentState() == Elevator::Overload || elevators[evNum - 1]->currentState() == Elevator::Emergency)
        ui->pushLeaveButton->setEnabled(true);
    else if(ui->pushLeaveButton->isEnabled())
        ui->pushLeaveButton->setEnabled(false);

    if(availableEv != nullptr && flr == availableEv->currentFloor())
        ui->pushMoveButton->setEnabled(true);
    else if(ui->pushMoveButton->isEnabled())
        ui->pushMoveButton->setEnabled(false);
}

void ElevatorController::elevatorSelected(int index)
{
    ui->passengerNumber->display(elevators[index]->numPassengers());

    updateDisplays();

    controlMoveButtonActivated(elevators[index]);


    qDebug()  << "COMBO BOX: Elevator selected. Elevator: " << index;
}

void ElevatorController::floorSelected(int index)
{
    // update the segment display for passangers
    ui->passengerOnFloorNumber->display(floors[index]->peopleOnFloor());
    qDebug()  << "COMBO BOX: Floor selected. Floor: " << index;

    ui->spinBoxMove->setValue(0); // wipe this since its different # ppl
    controlMoveButtonActivated(); // potentially changes move buttons state
}

void ElevatorController::moveComboBoxChange(int index)
{
    if(index > ui->passengerOnFloorNumber->value())
    {
        ui->spinBoxMove->setValue(ui->passengerOnFloorNumber->value());
    }
}

void ElevatorController::moveLeaveElevatorBoxChange(int index)
{
    if(index > ui->passengerNumber->value())
    {
        ui->spinBoxLeaveElevator->setValue(ui->passengerNumber->value());
    }
}

// --- UI UPDATE / EV SOCKET FUNCS ---

void ElevatorController::elevatorFloorChanged(int floor, int ev, bool up)
{
    // each elevator emits this when the moved to new floor
    ev -= 1;
    qDebug() << "EV signal: Elevator floor changed, floor: " << floor << " elevator: " << ev << " up dir: " << up;
    qDebug() << "(X, Y) : " << floor << ", " << (ev + 1);


    const int x = floors.size() - floor; // as the floors decrease, x increases (flr increase, x decrease)
    const int y = ev + 1;

    QLayoutItem* layoutItem = elevatorGridLayout->itemAtPosition(x, y); // check if we are looking at a valid ev
    if (!layoutItem)
    {

        qDebug() << "No layout item at this position.";
        return;
    }

    QWidget* widget = layoutItem->widget();
    if (!widget)
    {
        qDebug() << "No widget at this position.";
        return;
    }

    const QMetaObject* metaObject = widget->metaObject();
    QString widgetType = QString::fromUtf8(metaObject->className());

    if (widgetType == "QLabel")
    {
        QLabel* square = qobject_cast<QLabel*>(widget);
        QLabel* squarePrev;
    
        squarePrev = qobject_cast<QLabel*>(elevatorGridLayout->itemAtPosition((x - 1 + floors.size()) % floors.size(), y)->widget());
        squarePrev->setStyleSheet(QString("background-color: gray;"));
    
        squarePrev = qobject_cast<QLabel*>(elevatorGridLayout->itemAtPosition((x + 1)%floors.size(), y)->widget());
        squarePrev->setStyleSheet(QString("background-color: gray;"));
    
        if(elevators[ev]->currentState() == Elevator::Emergency)
            square->setStyleSheet("background-color: yellow;");
        else
            square->setStyleSheet("background-color: red;");
    }

    qDebug() << "Widget type: " << widgetType;
}

void ElevatorController::doorOpened(int flr, int ev)
{
    // a door has opened
    qDebug()  << "EV signal: Door opened! Elevator: " << ev;
    const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)
    const int y = ev;
    if (!elevatorGridLayout->itemAtPosition(x, y))
    {
        qDebug()  << "doorOpened(): No Item at position:  (" << x << ", " << y <<  ")";
        return;
    }
    QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();
    if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel")
    {
        qDebug()  << "doorOpened(): Item at position:  (" << x << ", " << y <<  ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());
        return;
    }
    QLabel* squarePrev = qobject_cast<QLabel*>(wdg);
    squarePrev->setStyleSheet(QString("background-color: green;"));
    controlMoveButtonActivated(elevators[ev - 1]);
    updateDisplays();
}

void ElevatorController::doorClosed(int flr, int ev)
{
    // a door has closed
    qDebug()  << "EV signal: Door closed!! Elevator: " << ev;
    const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)
    const int y = ev;

    if (!elevatorGridLayout->itemAtPosition(x, y))
    {
        qDebug()  << "doorClosed(): No Item at position:  (" << x << ", " << y <<  ")";
        return;
    }
    QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();
    if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel")
    {
        qDebug()  << "doorClosed(): Item at position:  (" << x << ", " << y <<  ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());
        return;
    }
    QLabel* squarePrev = qobject_cast<QLabel*>(wdg);
    squarePrev->setStyleSheet(QString("background-color: purple;"));
}

void ElevatorController::doorBlocked(int flr, int ev)
{
    // a door has closed
    qDebug()  << "EV signal: Alert! Door blocked... reopening door... Elevator: " << ev;
    const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)
    const int y = ev;

    if (!elevatorGridLayout->itemAtPosition(x, y))
    {
        qDebug()  << "doorBlocked(): No Item at position:  (" << x << ", " << y <<  ")";
        return;
    }
    QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();
    if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel")
    {
        qDebug()  << "doorBlocked(): Item at position:  (" << x << ", " << y <<  ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());
        return;
    }
    QLabel* squarePrev = qobject_cast<QLabel*>(wdg);
    squarePrev->setStyleSheet(QString("background-color: blue;"));
}

void ElevatorController::overloaded(int flr, int ev)
{
    // a door has closed
    qDebug()  << "EV signal: Elevator overloaded!! Elevator: " << ev;
    const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)
    const int y = ev;
    if (!elevatorGridLayout->itemAtPosition(x, y))
    {
        qDebug()  << "doorClosed(): No Item at position:  (" << x << ", " << y <<  ")";
        return;
    }
    QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();
    if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel")
    {
        qDebug()  << "overloaded(): Item at position:  (" << x << ", " << y <<  ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());
        return;
    }
    QLabel* squarePrev = qobject_cast<QLabel*>(wdg);
    squarePrev->setStyleSheet(QString("background-color: orange;"));
}

void ElevatorController::emergency(int flr, int ev)
{
    // a door has closed
    qDebug()  << "EV signal: Elevator emergency!! Elevator: " << ev;

    if(flr != SAFE_FLOOR)
        return;

    QLayoutItem* layoutItem = elevatorGridLayout->itemAtPosition(floors.size() - SAFE_FLOOR, ev); // check if we are looking at a valid ev
    if (!layoutItem)
    {
        qDebug() << "No layout item at this position.";
        return;
    }
    
    QWidget* widget = layoutItem->widget();
    if (!widget)
    {
        qDebug() << "No widget at this position.";
        return;
    }
    
    const QMetaObject* metaObject = widget->metaObject();
    QString widgetType = QString::fromUtf8(metaObject->className());
    if (widgetType == "QLabel")
    {
        QLabel* square = qobject_cast<QLabel*>(widget);
    
        if(elevators[ev - 1]->currentState() == Elevator::Idle)
            square->setStyleSheet(QString("background-color: red;"));
        else
            square->setStyleSheet(QString("background-color: yellow;"));
    } 

    qDebug() << "Widget type: " << widgetType;
}

// --- EV REQUEST FUNCS ---

void ElevatorController::buttonPressedUp(int floor)
{
    // an up button on a floor has been pressed
    qDebug()  << "Floor signal: Floor up button pressed: " << floor;
    handleFlrPressed(FloorDirection(floor, true));
}

void ElevatorController::buttonPressedDown(int floor)
{
    // a down button on a floor has been pressed
    qDebug() << "Floor signal: Floor down button pressed: " << floor;
    handleFlrPressed(FloorDirection(floor, false));
}

void ElevatorController::handleFlrPressed(FloorDirection fd)
{
    // maybe this had some use in some implementtation? ev->getNumFloorsReserved();

    Elevator* bestElevator = nullptr;
    Elevator* idleEv = nullptr; // lower prio
    for(Elevator* pEv : elevators)
    {
        if(fd.up && pEv->lastDirMovingUp() && fd.num >= pEv->currentFloor())
        {
            bestElevator = pEv;
            break;
        }
        if(!fd.up && !pEv->lastDirMovingUp() && fd.num <= pEv->currentFloor())
        {
            bestElevator = pEv;
            break;
        }

        if(pEv->currentState() == Elevator::Idle)
            idleEv = pEv;
    }

    if(bestElevator)
        emit moveElevatorToFloor(bestElevator->getId(), fd.num);
    else if(idleEv)
        emit moveElevatorToFloor(idleEv->getId(), fd.num);
    else
        earliestRequestTree.push(fd);
}

void ElevatorController::scanRequestTree()
{
    // happen on a timer, scan request tree realloc elevators if free
    if(AGGRESSIVE_LOGGING && !earliestRequestTree.empty())
        qDebug() << "scanRequestTree-> Request floor:  " << earliestRequestTree.top().num << " up: " << earliestRequestTree.top().up; // << i++;
    if (earliestRequestTree.empty())
    {
        return;
    }

    FloorDirection fd = earliestRequestTree.top();
    earliestRequestTree.pop();
    handleFlrPressed(FloorDirection(fd.num, fd.up));
}
xt

三、下载链接

https://download.csdn.net/download/u013083044/88861542

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/401900.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024「诺奖风向标」斯隆奖出炉:杨笛一、杜少雷、清华校友姜楠、北大校友金驰等入选​

今天&#xff0c;斯隆基金会公布了 2024年度斯隆研究奖&#xff08;Sloan Research Fellowship&#xff09;获得者名单&#xff0c;本次斯隆研究奖共颁发给了126 人&#xff0c;其中计算机科学领域 共有 7名华人学者当选。 包括斯坦福大学杨笛一&#xff08;上海交大ACM班校友…

2.5《Python3 网络爬虫开发实战》学习之实例实战1

目录 1 实战内容 2 确定思路 3 代码实操 3.1 实现一个个网页的爬取 3.2 爬取每一个网页的电影详情页url ​编辑 3.3 连接链接&#xff0c;针对每个详情页链接进行爬取、汇总内容 3.4 存储在txt文件中 4 结尾&#xff1a;整体代码 1 实战内容 爬取Scrape | Movie中所有…

24款奔驰S400L升级原厂360全景影像 效果分享

今天给大家分享一款 接近百万豪车 奔驰S400L商务版 连360 小柏林都没有&#xff0c;奔驰果然是不坑穷人的&#xff0c;所以很多车主一提到车就升级成豪华型的配置&#xff0c;你说五米多才的车 没有原厂360全景影像 是多么的难受 倒车和狭窄路段很麻烦&#xff0c;所以车主找到…

基于EasyCVR视频汇聚系统的公安网视频联网共享视频云平台建设思路分析(一)

随着社会的发展和科技的进步&#xff0c;视频监控系统在各个领域的应用越来越广泛&#xff0c;视频云平台建设已经成为了行业数字化转型的重要一环。公安网视频汇聚联网共享云的建设需要充分考虑技术、架构、安全、存储、计算等多方面因素&#xff0c;以确保平台的稳定性和可用…

基于ExtendSim的半导体制造工厂仿真

这是一个离散事件模型&#xff0c;使用ExtendeSim “高级资源管理&#xff08;ARM&#xff09;”功能来组织和分配资源。 此模型使用离散事件仿真和高级资源管理&#xff08;ARM&#xff09;功能。ARM是一个集成系统&#xff0c;用于组织资源、区分资源并在整个模型中分配资源。…

PHP实现分离金额和其他内容便于统计计算

得到的结果可以粘贴到excel计算 <?php if($_GET["x"] "cha"){ $tips isset($_POST[tips]) ? $_POST[tips] : ; $pattern /(\d\.\d|\d)/; $result preg_replace($pattern, "\t\${1}\t", $tips); echo "<h2><strong>数…

Linux离线安装插件

当公司Linux环境无外网情况下&#xff0c;需要先下载好离线安装包&#xff0c;然后上传到服务器&#xff0c;进行安装。 这里介绍一个下载插件安装包的网站&#xff0c;可以搜索到lrzsz、lsof、telnet、unzip、zip等安装包 搜索到想要的插件安装包后&#xff0c;下载并上传到服…

门控时钟基础知识

什么是门控时钟 RTL中的门控时钟 通常情况下&#xff0c;时钟树由大量的缓冲器和反相器组成&#xff0c;时钟信号为设计中翻转率最高的信号&#xff0c;时钟树的功耗可能高达整个设计功耗40%。 加入门控时钟电路后&#xff0c;由于减少了时钟树的翻转&#xff0c;节省了翻转功…

#LLM入门|Prompt#1.7_文本拓展_Expanding

输入简短文本&#xff0c;生成更加丰富的长文。 “温度”&#xff08;temperature&#xff09;&#xff1a;控制文本生成的多样性。 一、定制客户邮件 根据客户的评价和其中的情感倾向&#xff0c;使用大语言模型针对性地生成回复邮件。将大大提升客户满意度。 # 我们可以在…

分享6个当下最受欢迎的 Vue UI 库

在本文中&#xff0c;我列出了前 6个最受欢迎的&#xff08;根据 NPM 下载量和 Github stars&#xff0c;从上到下排名&#xff09;UI 库&#xff0c;供您启动您梦想中的 Vue 项目。 Vue.js 作为一个 JavaScript 框架&#xff0c;由于其简单、易用和学习曲线&#xff0c;是 Rea…

Facebook的未来蓝图:数字社交的下一个篇章

在数字化时代&#xff0c;社交媒体已经成为人们日常生活中不可或缺的一部分。而在众多的社交媒体平台中&#xff0c;Facebook一直处于领先地位&#xff0c;不断探索着数字社交的新领域和新形式。随着科技的不断发展和社会的不断变革&#xff0c;Facebook正在谱写着数字社交的未…

工业边缘网关的主要功能与应用价值分享-天拓四方

工业边缘网关&#xff0c;也称为工业物联网边缘计算网关&#xff0c;是一种部署在工业生产现场&#xff0c;具备数据采集、处理、存储和传输功能的智能设备。它能够将各种传感器、执行器、控制器等工业设备连接到网络&#xff0c;实现设备间的互联互通&#xff0c;同时提供边缘…

shapely 笔记 voronoi图

Voronoi 图是一种将平面分割成区域的方法&#xff0c;每个区域包含一个输入点&#xff0c;任何在该区域内的点都比其他输入点更接近该区域的输入点 1 基本使用方法 shapely.ops.voronoi_diagram(geom, envelopeNone, tolerance0.0, edgesFalse) 2 参数说明 geom任何几何类型…

船运物流管理系统|基于springboot船运物流管理系统设计与实现(源码+数据库+文档)

船运物流管理系统目录 目录 基于springboot船运物流管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员登录 2、货运单管理 3、公告管理 4、公告类型管理 5、新闻管理 6、新闻类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 …

Internet Download Manager 6.42.3 (IDM) 中文免激活绿色版

相信很多网友都遇到过一种情况&#xff0c;网页有些视频资源或者音频资源不知道如何下载&#xff0c;一直不知道如何解决&#xff0c;为此小编特意带来了这款&#xff1a;Internet Download Manager电脑版&#xff0c;这是一款非常专业且十分好用的下载工具&#xff0c;也就是大…

基于springboot + vue实现的前后端分离-酒店管理系统

项目介绍 基于springboot vue实现的酒店管理系统一共有酒店管理员和用户这两种角色。 管理员功能 登录&#xff1a;管理员可以通过登录功能进入系统&#xff0c;确保只有授权人员可以访问系统。用户管理&#xff1a;管理员可以添加、编辑和删除酒店的用户&#xff0c;包括前…

常见文档向量表示方法

参考&#xff1a;https://www.slidestalk.com/Milvus/doc2vecmilvus85394 相似文章召回&#xff0c;通常是指在信息检索、自然语言处理等领域中的一种技术手段。它的主要功能是根据用户提供的某篇文章或一段文本&#xff0c;通过算法模型快速、准确地从海量文本库中找出与之主题…

第二证券:权重板块引领市场走高 20只绩优大盘股仍超跌

2月21日&#xff0c;A股商场再现普涨行情&#xff0c;上证指数盘中一度逼近3000点关口。权重股扎堆的沪深300指数上涨1.35%&#xff0c;领涨其他指数。北上资金也大举加仓&#xff0c;全天净流入近136亿元&#xff0c;其间沪股通净流入96.41亿元&#xff0c;深股通净流入39.54亿…

源聚达电商:现在的抖音小店卖啥赚钱

在数字浪潮中&#xff0c;抖音小店如同一叶扁舟&#xff0c;乘风破浪于电商海洋。何为赚钱之本?答案藏匿在消费者的喜好与市场的缝隙之中。今日&#xff0c;让我们一同探索抖音小店盈利的秘诀。 个性化商品是小店的灵魂。消费者渴望独一无二&#xff0c;定制化产品如手工艺品、…

代码随想录算法训练营第二十四天 | 回溯算法理论基础,77. 组合 [回溯篇]

代码随想录算法训练营第二十四天 回溯算法理论基础什么是回溯法回溯法的理解回溯法模板 LeetCode 77.组合题目描述思路参考代码总结优化版本 回溯算法理论基础 文章讲解&#xff1a;代码随想录#回溯算法理论基础 视频讲解&#xff1a;带你学透回溯算法&#xff08;理论篇&#…