Merge branch 'master' of https://fsunuc.physics.fsu.edu/git/rtang/FSUDAQ_Qt6
This commit is contained in:
commit
94bae83a65
|
@ -667,7 +667,7 @@ unsigned int Digitizer::CalByteForBufferCAEN(){
|
||||||
uint32_t AllocatedSize;
|
uint32_t AllocatedSize;
|
||||||
ret = CAEN_DGTZ_MallocReadoutBuffer(handle, &BufferCAEN, &AllocatedSize);
|
ret = CAEN_DGTZ_MallocReadoutBuffer(handle, &BufferCAEN, &AllocatedSize);
|
||||||
|
|
||||||
delete BufferCAEN;
|
if( BufferCAEN) delete BufferCAEN;
|
||||||
return AllocatedSize;
|
return AllocatedSize;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,13 +40,16 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr
|
||||||
enableSignalSlot = false;
|
enableSignalSlot = false;
|
||||||
|
|
||||||
setWindowTitle("Digitizer Settings");
|
setWindowTitle("Digitizer Settings");
|
||||||
setGeometry(0, 0, 1700, 850);
|
|
||||||
|
|
||||||
//====== resize window if screen too small
|
//====== resize window if screen too small
|
||||||
QScreen * screen = QGuiApplication::primaryScreen();
|
QScreen * screen = QGuiApplication::primaryScreen();
|
||||||
QRect screenGeo = screen->geometry();
|
QRect screenGeo = screen->geometry();
|
||||||
if( screenGeo.width() < 1700 || screenGeo.height() < 850) this->showMaximized();
|
if( screenGeo.width() < 1700 || screenGeo.height() < 850) {
|
||||||
|
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||||
|
}else{
|
||||||
|
setGeometry(0, 0, 1700, 850);
|
||||||
|
}
|
||||||
|
// setGeometry(0, 0, 1700, 850);
|
||||||
|
|
||||||
tabWidget = new QTabWidget(this);
|
tabWidget = new QTabWidget(this);
|
||||||
setCentralWidget(tabWidget);
|
setCentralWidget(tabWidget);
|
||||||
|
@ -266,7 +269,7 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr
|
||||||
// connect(bnSaveSettingsToText, &QPushButton::clicked, this, [=](){ SaveSetting(1);});
|
// connect(bnSaveSettingsToText, &QPushButton::clicked, this, [=](){ SaveSetting(1);});
|
||||||
|
|
||||||
//checkBox, to coupled or decouple the setting file.
|
//checkBox, to coupled or decouple the setting file.
|
||||||
chkCoupledSettingFile = new QCheckBox("Update Setting", this);
|
chkCoupledSettingFile = new QCheckBox("Live Setting Update", this);
|
||||||
buttonLayout->addWidget(chkCoupledSettingFile, rowID, 2);
|
buttonLayout->addWidget(chkCoupledSettingFile, rowID, 2);
|
||||||
chkCoupledSettingFile->setCheckState(Qt::CheckState::Unchecked);
|
chkCoupledSettingFile->setCheckState(Qt::CheckState::Unchecked);
|
||||||
connect(chkCoupledSettingFile, &QCheckBox::stateChanged, this, [=](int state){
|
connect(chkCoupledSettingFile, &QCheckBox::stateChanged, this, [=](int state){
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
#include "analyzers/CoincidentAnalyzer.h"
|
#include "analyzers/CoincidentAnalyzer.h"
|
||||||
#include "analyzers/SplitPoleAnalyzer.h"
|
#include "analyzers/SplitPoleAnalyzer.h"
|
||||||
#include "analyzers/EncoreAnalyzer.h"
|
#include "analyzers/EncoreAnalyzer.h"
|
||||||
|
#include "analyzers/MUSICAnalyzer.h"
|
||||||
#include "analyzers/RAISOR.h"
|
#include "analyzers/RAISOR.h"
|
||||||
|
|
||||||
std::vector<std::string> onlineAnalyzerList = {"Coincident","Splie-Pole", "Encore", "RAISOR"};
|
std::vector<std::string> onlineAnalyzerList = {"Coincident","Splie-Pole", "Encore", "RAISOR", "MUSICS"};
|
||||||
|
|
||||||
FSUDAQ::FSUDAQ(QWidget *parent) : QMainWindow(parent){
|
FSUDAQ::FSUDAQ(QWidget *parent) : QMainWindow(parent){
|
||||||
DebugPrint("%s", "FSUDAQ");
|
DebugPrint("%s", "FSUDAQ");
|
||||||
|
@ -1827,6 +1828,7 @@ void FSUDAQ::OpenAnalyzer(){
|
||||||
if( id == 1 ) onlineAnalyzer = new SplitPole(digi, nDigi);
|
if( id == 1 ) onlineAnalyzer = new SplitPole(digi, nDigi);
|
||||||
if( id == 2 ) onlineAnalyzer = new Encore(digi, nDigi);
|
if( id == 2 ) onlineAnalyzer = new Encore(digi, nDigi);
|
||||||
if( id == 3 ) onlineAnalyzer = new RAISOR(digi, nDigi);
|
if( id == 3 ) onlineAnalyzer = new RAISOR(digi, nDigi);
|
||||||
|
if( id == 4 ) onlineAnalyzer = new MUSIC(digi, nDigi);
|
||||||
if( id >= 0 ) onlineAnalyzer->show();
|
if( id >= 0 ) onlineAnalyzer->show();
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
|
@ -1836,6 +1838,7 @@ void FSUDAQ::OpenAnalyzer(){
|
||||||
if( id == 1 ) onlineAnalyzer = new SplitPole(digi, nDigi);
|
if( id == 1 ) onlineAnalyzer = new SplitPole(digi, nDigi);
|
||||||
if( id == 2 ) onlineAnalyzer = new Encore(digi, nDigi);
|
if( id == 2 ) onlineAnalyzer = new Encore(digi, nDigi);
|
||||||
if( id == 3 ) onlineAnalyzer = new RAISOR(digi, nDigi);
|
if( id == 3 ) onlineAnalyzer = new RAISOR(digi, nDigi);
|
||||||
|
if( id == 4 ) onlineAnalyzer = new MUSIC(digi, nDigi);
|
||||||
|
|
||||||
if( id >= 0 ){
|
if( id >= 0 ){
|
||||||
onlineAnalyzer->show();
|
onlineAnalyzer->show();
|
||||||
|
|
|
@ -279,6 +279,8 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){
|
||||||
if( timeWindow <= 0 ) break;
|
if( timeWindow <= 0 ) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( events[eventIndex].size() == 0 ) continue;
|
||||||
|
|
||||||
if( events[eventIndex].size() > 1) {
|
if( events[eventIndex].size() > 1) {
|
||||||
std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) {
|
std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) {
|
||||||
return a.timestamp < b.timestamp;
|
return a.timestamp < b.timestamp;
|
||||||
|
|
10
Scope.cpp
10
Scope.cpp
|
@ -6,7 +6,7 @@
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QScreen>
|
// #include <QScreen>
|
||||||
|
|
||||||
QVector<QPointF> Scope::TrapezoidFilter(QVector<QPointF> data, int baseLineEndS, int riseTimeS, int flatTopS, float decayTime_ns){
|
QVector<QPointF> Scope::TrapezoidFilter(QVector<QPointF> data, int baseLineEndS, int riseTimeS, int flatTopS, float decayTime_ns){
|
||||||
DebugPrint("%s", "Scope");
|
DebugPrint("%s", "Scope");
|
||||||
|
@ -54,13 +54,17 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh
|
||||||
this->readDataThread = readDataThread;
|
this->readDataThread = readDataThread;
|
||||||
|
|
||||||
setWindowTitle("Scope");
|
setWindowTitle("Scope");
|
||||||
setGeometry(0, 0, 1000, 800);
|
|
||||||
setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint );
|
setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint );
|
||||||
|
|
||||||
//====== resize window if screen too small
|
//====== resize window if screen too small
|
||||||
QScreen * screen = QGuiApplication::primaryScreen();
|
QScreen * screen = QGuiApplication::primaryScreen();
|
||||||
QRect screenGeo = screen->geometry();
|
QRect screenGeo = screen->geometry();
|
||||||
if( screenGeo.width() < 1000 || screenGeo.height() < 800) this->showMaximized();
|
if( screenGeo.width() < 1000 || screenGeo.height() < 800) {
|
||||||
|
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||||
|
}else{
|
||||||
|
setGeometry(0, 0, 1000, 800);
|
||||||
|
}
|
||||||
|
// setGeometry(0, 0, 1000, 800);
|
||||||
|
|
||||||
enableSignalSlot = false;
|
enableSignalSlot = false;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QScreen>
|
// #include <QScreen>
|
||||||
|
|
||||||
SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawDataPath, QMainWindow * parent) : QMainWindow(parent){
|
SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawDataPath, QMainWindow * parent) : QMainWindow(parent){
|
||||||
DebugPrint("%s", "SingleSpectra");
|
DebugPrint("%s", "SingleSpectra");
|
||||||
|
@ -18,13 +18,18 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD
|
||||||
isSignalSlotActive = true;
|
isSignalSlotActive = true;
|
||||||
|
|
||||||
setWindowTitle("Single Histograms");
|
setWindowTitle("Single Histograms");
|
||||||
setGeometry(0, 0, 1000, 800);
|
|
||||||
//setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint );
|
//setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint );
|
||||||
|
|
||||||
//====== resize window if screen too small
|
//====== resize window if screen too small
|
||||||
QScreen * screen = QGuiApplication::primaryScreen();
|
QScreen * screen = QGuiApplication::primaryScreen();
|
||||||
QRect screenGeo = screen->geometry();
|
QRect screenGeo = screen->geometry();
|
||||||
if( screenGeo.width() < 1000 || screenGeo.height() < 800) this->showMaximized();
|
if( screenGeo.width() < 1000 || screenGeo.height() < 800) {
|
||||||
|
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||||
|
}else{
|
||||||
|
setGeometry(0, 0, 1000, 800);
|
||||||
|
}
|
||||||
|
// setGeometry(0, 0, 1000, 800);
|
||||||
|
|
||||||
QWidget * layoutWidget = new QWidget(this);
|
QWidget * layoutWidget = new QWidget(this);
|
||||||
setCentralWidget(layoutWidget);
|
setCentralWidget(layoutWidget);
|
||||||
|
|
|
@ -98,7 +98,7 @@ void Analyzer::BuildEvents(bool verbose){
|
||||||
if( isBuildBackward ){
|
if( isBuildBackward ){
|
||||||
mb->BuildEventsBackWard(maxNumEventBuilt, verbose);
|
mb->BuildEventsBackWard(maxNumEventBuilt, verbose);
|
||||||
}else{
|
}else{
|
||||||
mb->BuildEvents(0, 0, verbose);
|
mb->BuildEvents(0, true, verbose);
|
||||||
}
|
}
|
||||||
for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].unlock();
|
for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].unlock();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QScreen>
|
// #include <QScreen>
|
||||||
|
|
||||||
namespace EncoreChMap{
|
namespace EncoreChMap{
|
||||||
|
|
||||||
|
@ -84,13 +84,15 @@ private:
|
||||||
|
|
||||||
inline void Encore::SetUpCanvas(){
|
inline void Encore::SetUpCanvas(){
|
||||||
|
|
||||||
setGeometry(0, 0, 1600, 1600);
|
|
||||||
|
|
||||||
//====== resize window if screen too small
|
//====== resize window if screen too small
|
||||||
QScreen * screen = QGuiApplication::primaryScreen();
|
QScreen * screen = QGuiApplication::primaryScreen();
|
||||||
QRect screenGeo = screen->geometry();
|
QRect screenGeo = screen->geometry();
|
||||||
if( screenGeo.width() < 1600 || screenGeo.height() < 1600) this->showMaximized();
|
if( screenGeo.width() < 1000 || screenGeo.height() < 1000) {
|
||||||
|
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() -100);
|
||||||
|
}else{
|
||||||
|
setGeometry(0, 0, 1000, 1000);
|
||||||
|
}
|
||||||
|
// setGeometry(0, 0, 1600, 1600);
|
||||||
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||||
layout->addWidget(chkRunAnalyzer, 0, 0);
|
layout->addWidget(chkRunAnalyzer, 0, 0);
|
||||||
|
|
||||||
|
|
178
analyzers/MUSICAnalyzer.h
Normal file
178
analyzers/MUSICAnalyzer.h
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
#ifndef MUSICANLAYZER_H
|
||||||
|
#define MUSICANLAYZER_H
|
||||||
|
|
||||||
|
#include "Analyser.h"
|
||||||
|
#include "Isotope.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <QApplication>
|
||||||
|
// #include <QScreen>
|
||||||
|
|
||||||
|
namespace MUSICChMap{
|
||||||
|
|
||||||
|
const std::map<unsigned short, int> SN2Bd = {
|
||||||
|
{16828, 0},
|
||||||
|
{16829, 1},
|
||||||
|
{16827, 2},
|
||||||
|
{23986, 3}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Left 0->15
|
||||||
|
//Right 16->31
|
||||||
|
//Individual{32=Grid, 33=S0, 34=cathode, 35=S17, 36=Si_dE, 100>pulser},
|
||||||
|
//-1=empty
|
||||||
|
const int mapping[4][16] = {
|
||||||
|
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||||
|
{34, -1, 1, -1, 33, 101, 5, -1, 0, -1, 9, -1, 17, 13, -1, 32},
|
||||||
|
{ 2, -1, 16, -1, 21, 102, 20, -1, 8, -1, 24, -1, 27, 28, -1, 14},
|
||||||
|
{19, -1, 3, -1, 6, 103, 7, -1, 25, -1, 11, -1, 12, 15, -1, 10},
|
||||||
|
{ 4, -1, 18, 36, 23, 104, 22, -1, 29, -1, 26, -1, 31, 30, -1, 35}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gain matching [ch][bd]
|
||||||
|
const double corr[16][4] = {
|
||||||
|
{ 1.00000, 1.00000, 1.00000, 1.0000},
|
||||||
|
{ 1.00000, 1.00000, 1.03158, 1.0000},
|
||||||
|
{ 1.00000, 1.00000, 0.99240, 1.0000},
|
||||||
|
{ 1.00000, 1.03704, 0.94004, 1.0000},
|
||||||
|
{ 1.01031, 1.02084, 1.10114, 1.0000},
|
||||||
|
{ 1.00000, 0.94685, 1.00513, 1.0000},
|
||||||
|
{ 1.00000, 1.03431, 1.00513, 1.0000},
|
||||||
|
{ 1.00000, 0.92670, 0.96078, 1.0000},
|
||||||
|
{ 1.03431, 0.94685, 0.96314, 1.0000},
|
||||||
|
{ 1.00000, 1.03158, 0.95145, 1.0000},
|
||||||
|
{ 0.95145, 1.00256, 0.97270, 1.0000},
|
||||||
|
{ 1.00000, 1.00256, 0.90950, 1.0000},
|
||||||
|
{ 1.03704, 0.99492, 0.98740, 1.0000},
|
||||||
|
{ 1.00000, 1.00000, 0.99746, 1.0000},
|
||||||
|
{ 0.96078, 1.03980, 1.00513, 1.0000},
|
||||||
|
{ 1.00000, 1.05095, 1.00000, 1.0000},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class MUSIC : public Analyzer{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
MUSIC(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||||
|
|
||||||
|
SetUpdateTimeInSec(1.0);
|
||||||
|
|
||||||
|
SetBackwardBuild(true, 100); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100.
|
||||||
|
evtbder = GetEventBuilder();
|
||||||
|
evtbder->SetTimeWindow(10000);
|
||||||
|
|
||||||
|
SetUpCanvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MUSIC(){};
|
||||||
|
|
||||||
|
void SetUpCanvas();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void UpdateHistograms();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MultiBuilder *evtbder;
|
||||||
|
|
||||||
|
Histogram2D * hLeft;
|
||||||
|
Histogram2D * hRight;
|
||||||
|
Histogram2D * hLR;
|
||||||
|
|
||||||
|
Histogram1D * hMulti;
|
||||||
|
|
||||||
|
QCheckBox * chkRunAnalyzer;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline void MUSIC::SetUpCanvas(){
|
||||||
|
|
||||||
|
//====== resize window if screen too small
|
||||||
|
QScreen * screen = QGuiApplication::primaryScreen();
|
||||||
|
QRect screenGeo = screen->geometry();
|
||||||
|
if( screenGeo.width() < 1000 || screenGeo.height() < 1000) {
|
||||||
|
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() -100);
|
||||||
|
}else{
|
||||||
|
setGeometry(0, 0, 1000, 1000);
|
||||||
|
}
|
||||||
|
// setGeometry(0, 0, 1600, 1600);
|
||||||
|
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||||
|
layout->addWidget(chkRunAnalyzer, 0, 0);
|
||||||
|
|
||||||
|
hLeft = new Histogram2D("Left", "Ch", "Energy", 16, 0, 16, 200, 0, 200, this);
|
||||||
|
layout->addWidget(hLeft, 1, 0);
|
||||||
|
hRight = new Histogram2D("Right", "Ch", "Energy", 16, 0, 16, 200, 0, 200, this);
|
||||||
|
layout->addWidget(hRight, 1, 1);
|
||||||
|
hLR = new Histogram2D("Left + Right", "Ch", "Energy", 17, 0, 16, 200, 0, 200, this);
|
||||||
|
layout->addWidget(hLR, 2, 0);
|
||||||
|
hMulti = new Histogram1D("Multi", "multiplicity", 40, 0, 40);
|
||||||
|
layout->addWidget(hMulti, 2, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MUSIC::UpdateHistograms(){
|
||||||
|
|
||||||
|
if( this->isVisible() == false ) return;
|
||||||
|
if( chkRunAnalyzer->isChecked() == false ) return;
|
||||||
|
|
||||||
|
BuildEvents(false); // call the event builder to build events
|
||||||
|
|
||||||
|
//============ Get events, and do analysis
|
||||||
|
long eventBuilt = evtbder->eventBuilt;
|
||||||
|
if( eventBuilt == 0 ) return;
|
||||||
|
|
||||||
|
//============ Processing data and fill histograms
|
||||||
|
long eventIndex = evtbder->eventIndex;
|
||||||
|
long eventStart = eventIndex - eventBuilt + 1;
|
||||||
|
if(eventStart < 0 ) eventStart += MaxNEvent;
|
||||||
|
|
||||||
|
// printf("MUSIC::%s----------- 2 : %ld %ld \n", __func__, eventStart, eventIndex);
|
||||||
|
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||||
|
std::vector<Hit> event = evtbder->events[i];
|
||||||
|
// printf("MUSIC::%s----------- %ld, %zu\n", __func__, i, event.size());
|
||||||
|
|
||||||
|
hMulti->Fill((int) event.size());
|
||||||
|
if( event.size() == 0 ) return;
|
||||||
|
|
||||||
|
double sum[17] = {0};
|
||||||
|
for( int k = 0; k < (int) event.size(); k++ ){
|
||||||
|
|
||||||
|
// printf("--- %d\n", k);
|
||||||
|
int bd = MUSICChMap::SN2Bd.at(event[k].sn);
|
||||||
|
int ch = event[k].ch;
|
||||||
|
|
||||||
|
int ID = MUSICChMap::mapping[bd][ch];
|
||||||
|
|
||||||
|
if( ID < 0 ) continue;
|
||||||
|
|
||||||
|
double eC = event[k].energy;
|
||||||
|
if( 0 <= ID && ID < 16 ) {
|
||||||
|
eC *= MUSICChMap::corr[ch][bd];
|
||||||
|
hLeft->Fill(ID, eC);
|
||||||
|
sum[ID] += eC;
|
||||||
|
}
|
||||||
|
if( 16 <= ID && ID < 32 ) {
|
||||||
|
eC *= MUSICChMap::corr[ch][bd];
|
||||||
|
hRight->Fill(ID-16, eC );
|
||||||
|
sum[ID-16] += eC ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int ch = 0; ch < 17; ch++){
|
||||||
|
if( sum[ch] > 0 ) hLR->Fill(ch, sum[ch]);
|
||||||
|
//printf("%d | sum %d\n", ch, sum[ch]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hLeft->UpdatePlot();
|
||||||
|
hRight->UpdatePlot();
|
||||||
|
hMulti->UpdatePlot();
|
||||||
|
hLR->UpdatePlot();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user