File indexing completed on 2024-07-14 07:17:24

0001 /*
0002     SPDX-FileCopyrightText: 2008 Akarsh Simha <akarshsimha@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "starblockfactory.h"
0008 
0009 #include "starblock.h"
0010 #include "starobject.h"
0011 
0012 #include <kstars_debug.h>
0013 
0014 // TODO: Implement a better way of deciding this
0015 #define DEFAULT_NCACHE 12
0016 
0017 StarBlockFactory *StarBlockFactory::pInstance = nullptr;
0018 
0019 StarBlockFactory *StarBlockFactory::Instance()
0020 {
0021     if (!pInstance)
0022         pInstance = new StarBlockFactory();
0023     return pInstance;
0024 }
0025 
0026 StarBlockFactory::StarBlockFactory()
0027 {
0028     first   = nullptr;
0029     last    = nullptr;
0030     nBlocks = 0;
0031     drawID  = 0;
0032     nCache  = DEFAULT_NCACHE;
0033 }
0034 
0035 StarBlockFactory::~StarBlockFactory()
0036 {
0037     deleteBlocks(nBlocks);
0038     if (pInstance)
0039         pInstance = nullptr;
0040 }
0041 
0042 std::shared_ptr<StarBlock> StarBlockFactory::getBlock()
0043 {
0044     std::shared_ptr<StarBlock> freeBlock;
0045 
0046     if (nBlocks < nCache)
0047     {
0048         freeBlock.reset(new StarBlock);
0049         if (freeBlock.get())
0050         {
0051             ++nBlocks;
0052             return freeBlock;
0053         }
0054     }
0055     if (last && (last->drawID != drawID || last->drawID == 0))
0056     {
0057         //        qCDebug(KSTARS) << "Recycling block with drawID =" << last->drawID << "and current drawID =" << drawID;
0058         if (last->parent->block(last->parent->getBlockCount() - 1) != last)
0059             qCDebug(KSTARS) << "ERROR: Goof up here!";
0060         freeBlock = last;
0061         last      = last->prev;
0062         if (last)
0063         {
0064             last->next = nullptr;
0065         }
0066         if (freeBlock == first)
0067         {
0068             first = nullptr;
0069         }
0070         freeBlock->reset();
0071         freeBlock->prev = nullptr;
0072         freeBlock->next = nullptr;
0073         return freeBlock;
0074     }
0075     freeBlock.reset(new StarBlock);
0076     if (freeBlock.get())
0077         ++nBlocks;
0078 
0079     return freeBlock;
0080 }
0081 
0082 bool StarBlockFactory::markFirst(std::shared_ptr<StarBlock>& block)
0083 {
0084     if (!block.get())
0085         return false;
0086 
0087     //    fprintf(stderr, "markFirst()!\n");
0088     if (!first)
0089     {
0090         //        qCDebug(KSTARS) << "INFO: Linking in first block";
0091         last = first = block;
0092         first->prev = first->next = nullptr;
0093         first->drawID             = drawID;
0094         return true;
0095     }
0096 
0097     if (block == first) // Block is already in the front
0098     {
0099         block->drawID = drawID;
0100         return true;
0101     }
0102 
0103     if (block == last)
0104         last = block->prev;
0105 
0106     if (block->prev)
0107         block->prev->next = block->next;
0108 
0109     if (block->next)
0110         block->next->prev = block->prev;
0111 
0112     first->prev = block;
0113     block->next = first;
0114     block->prev = nullptr;
0115     first       = block;
0116 
0117     block->drawID = drawID;
0118 
0119     return true;
0120 }
0121 
0122 bool StarBlockFactory::markNext(std::shared_ptr<StarBlock>& after, std::shared_ptr<StarBlock>& block)
0123 {
0124     //    fprintf(stderr, "markNext()!\n");
0125     if (!block.get() || !after.get())
0126     {
0127         qCDebug(KSTARS) << "WARNING: markNext called with nullptr argument";
0128         return false;
0129     }
0130 
0131     if (!first.get())
0132     {
0133         qCDebug(KSTARS) << "WARNING: markNext called without an existing linked list";
0134         return false;
0135     }
0136 
0137     if (block == after)
0138     {
0139         qCDebug(KSTARS) << "ERROR: Trying to mark a block after itself!";
0140         return false;
0141     }
0142 
0143     if (block->prev == after) // Block is already after 'after'
0144     {
0145         block->drawID = drawID;
0146         return true;
0147     }
0148 
0149     if (block == first)
0150     {
0151         if (block->next == nullptr)
0152         {
0153             qCDebug(KSTARS) << "ERROR: Trying to mark only block after some other block";
0154             return false;
0155         }
0156         first = block->next;
0157     }
0158 
0159     if (after->getFaintMag() > block->getFaintMag() && block->getFaintMag() != -5)
0160     {
0161         qCDebug(KSTARS) << "WARNING: Marking block with faint mag = " << block->getFaintMag() << " after block with faint mag "
0162                  << after->getFaintMag() << "in trixel" << block->parent->getTrixel();
0163     }
0164 
0165     if (block == last)
0166         last = block->prev;
0167 
0168     if (block->prev)
0169         block->prev->next = block->next;
0170     if (block->next)
0171         block->next->prev = block->prev;
0172 
0173     block->next = after->next;
0174     if (block->next)
0175         block->next->prev = block;
0176     block->prev = after;
0177     after->next = block;
0178 
0179     if (after == last)
0180         last = block;
0181 
0182     block->drawID = drawID;
0183 
0184     return true;
0185 }
0186 
0187 /*
0188 bool StarBlockFactory::groupMove( StarBlock *start, const int nblocks ) {
0189 
0190     StarBlock * end = nullptr;
0191 
0192     // Check for trivial cases
0193     if( !start || nblocks < 0 )
0194         return false;
0195 
0196     if( nblocks == 0 )
0197         return true;
0198 
0199     if( !first )
0200         return false;
0201 
0202     // Check for premature end
0203     end = start;
0204     for( int i = 1; i < nblocks; ++i ) {
0205         if( end == nullptr )
0206             return false;
0207         end = end->next;
0208     }
0209     if( end == nullptr )
0210         return false;
0211 
0212     // Update drawIDs
0213     end = start;
0214     for( int i = 1; i < nblocks; ++i ) {
0215         end->drawID = drawID;
0216         end = end->next;
0217     }
0218     end->drawID = drawID;
0219 
0220     // Check if we are already in the front
0221     if( !start->prev )
0222         return true;
0223 
0224     start->prev->next = end->next;
0225     end->next->prev = start->prev;
0226 
0227     first->prev = end;
0228     end->next = first;
0229     start->prev = nullptr;
0230     first = start;
0231 }
0232 */
0233 
0234 int StarBlockFactory::deleteBlocks(int nblocks)
0235 {
0236     int i           = 0;
0237     std::shared_ptr<StarBlock> temp;
0238 
0239     while (last != nullptr && i != nblocks)
0240     {
0241         temp = last->prev;
0242         last.reset();
0243         last = temp;
0244         i++;
0245     }
0246     if (last)
0247         last->next = nullptr;
0248     else
0249         first = nullptr;
0250 
0251     qCDebug(KSTARS) << nblocks << "StarBlocks freed from StarBlockFactory";
0252 
0253     nBlocks -= i;
0254     return i;
0255 }
0256 
0257 void StarBlockFactory::printStructure() const
0258 {
0259     std::shared_ptr<StarBlock> cur;
0260     Trixel curTrixel = 513; // TODO: Change if we change HTMesh level
0261     int index        = 0;
0262     bool draw        = false;
0263 
0264     cur = first;
0265     do
0266     {
0267         if (curTrixel != cur->parent->getTrixel())
0268         {
0269             qCDebug(KSTARS) << "Trixel" << cur->parent->getTrixel() << "starts at index" << index;
0270             curTrixel = cur->parent->getTrixel();
0271         }
0272         if (cur->drawID == drawID && !draw)
0273         {
0274             qCDebug(KSTARS) << "Blocks from index" << index << "are drawn";
0275             draw = true;
0276         }
0277         if (cur->drawID != drawID && draw)
0278         {
0279             qCDebug(KSTARS) << "Blocks from index" << index << "are not drawn";
0280             draw = false;
0281         }
0282         cur = cur->next;
0283         ++index;
0284     } while (cur != last);
0285 }
0286 
0287 int StarBlockFactory::freeUnused()
0288 {
0289     int i           = 0;
0290     std::shared_ptr<StarBlock> temp;
0291 
0292     while (last != nullptr && last->drawID < drawID && i != nBlocks)
0293     {
0294         temp = last->prev;
0295         last.reset();
0296         last = temp;
0297         i++;
0298     }
0299     if (last)
0300         last->next = nullptr;
0301     else
0302         first = nullptr;
0303 
0304     qCDebug(KSTARS) << i << "StarBlocks freed from StarBlockFactory";
0305 
0306     nBlocks -= i;
0307     return i;
0308 }