From f45706ffb08c0dae23fcc6818c98a64617a05791 Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@tu-dortmund.de>
Date: Fri, 18 Sep 2020 17:37:13 +0200
Subject: [PATCH] make HStackView friend of StackIteratorInterface

make Event non-templated, store index instead of StackIterator

HStackView as drop-in replacement for SecondaryView

started testHistory with HStackView

renamed HStackView to HSecondaryView
---
 .../StackInterface/StackIteratorInterface.h   |  8 +++
 Stack/History/CMakeLists.txt                  |  2 +-
 Stack/History/Event.hpp                       | 13 ++--
 Stack/History/HSecondaryView.hpp              | 48 ++++++++++++++
 Stack/History/HStackView.hpp                  | 39 -----------
 Stack/History/HistoryStackExtension.h         | 12 ++--
 Stack/History/SecondaryParticle.hpp           |  4 +-
 Stack/History/testHistory.cc                  | 66 ++++++++-----------
 8 files changed, 101 insertions(+), 91 deletions(-)
 create mode 100644 Stack/History/HSecondaryView.hpp
 delete mode 100644 Stack/History/HStackView.hpp

diff --git a/Framework/StackInterface/StackIteratorInterface.h b/Framework/StackInterface/StackIteratorInterface.h
index 5213e30d4..2aa5de889 100644
--- a/Framework/StackInterface/StackIteratorInterface.h
+++ b/Framework/StackInterface/StackIteratorInterface.h
@@ -10,6 +10,11 @@
 
 #include <corsika/stack/ParticleBase.h>
 
+namespace corsika::history {
+  template <typename T>
+  class HSecondaryView; // forward decl. for befriending
+}
+
 namespace corsika::stack {
 
   template <typename StackDataType, template <typename> typename ParticleInterface>
@@ -76,6 +81,9 @@ namespace corsika::stack {
     friend class SecondaryView<StackDataType,
                                ParticleInterface>; // access for SecondaryView
 
+    template <typename T>
+    friend class corsika::history::HSecondaryView;
+
   private:
     unsigned int fIndex = 0;
     StackType* fData = 0; // info: Particles and StackIterators become invalid when parent
diff --git a/Stack/History/CMakeLists.txt b/Stack/History/CMakeLists.txt
index 8b327411f..63b6b602c 100644
--- a/Stack/History/CMakeLists.txt
+++ b/Stack/History/CMakeLists.txt
@@ -1,7 +1,7 @@
 set (
   SETUP_HEADERS
   Event.hpp
-  HStackView.hpp
+  HSecondaryView.hpp
   HistoryStackExtension.h
   SecondaryParticle.hpp
   )
diff --git a/Stack/History/Event.hpp b/Stack/History/Event.hpp
index 82d949a7b..ebb5d3a2a 100644
--- a/Stack/History/Event.hpp
+++ b/Stack/History/Event.hpp
@@ -9,17 +9,16 @@
 #pragma once
 
 #include <corsika/particles/ParticleProperties.h>
-#include <corsika/stack/Stack.h>
 #include <corsika/history/SecondaryParticle.hpp>
 
+#include <iostream>
 #include <optional>
 #include <vector>
 
 namespace corsika::history {
 
-  template <typename TStackIterator>
-  class Event {
-    TStackIterator const projectile_; //!< reference to projectile
+  struct Event {
+    size_t const projectileIndex_; //!< reference to projectile
     std::vector<SecondaryParticle> secondaries;
 
     // meta information, could also be in a separate class
@@ -27,8 +26,10 @@ namespace corsika::history {
         targetCode; // cannot be const, value set only after construction
 
   public:
-    Event(TStackIterator projectile)
-        : projectile_{projectile} {}
+    Event(size_t projectileIndex)
+        : projectileIndex_{projectileIndex} {
+      std::cout << "Event created (index = " << projectileIndex_ << ")" << std::endl;
+    }
   };
 
 } // namespace corsika::history
diff --git a/Stack/History/HSecondaryView.hpp b/Stack/History/HSecondaryView.hpp
new file mode 100644
index 000000000..1abf8cf6b
--- /dev/null
+++ b/Stack/History/HSecondaryView.hpp
@@ -0,0 +1,48 @@
+/*
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+
+#pragma once
+
+#include <corsika/stack/SecondaryView.h>
+#include <corsika/history/Event.hpp>
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace corsika::history {
+
+  namespace detail {
+    template <typename TParticleIterator>
+    using SecondaryViewTypeFromIterator =
+        decltype(stack::SecondaryView{std::declval<TParticleIterator&>()});
+  }
+
+  template <typename TParticleIterator>
+  class HSecondaryView : public detail::SecondaryViewTypeFromIterator<TParticleIterator> {
+    std::shared_ptr<Event> event_;
+
+    using BaseSecondaryViewType =
+        detail::SecondaryViewTypeFromIterator<TParticleIterator>;
+
+  public:
+    HSecondaryView(TParticleIterator& p)
+        : BaseSecondaryViewType{p}
+        , event_{std::make_shared<Event>(p.GetIndex())} {}
+
+    template <typename... Args>
+    void AddSecondary(Args&&... args) {
+      auto const s = BaseSecondaryViewType::AddSecondary(
+          std::forward<Args...>(args...), event_); // what if event is not last argument?
+      event_->secondaries.emplace_back(s.GetEnergy(), s.GetMomentum(), s.GetParticleID());
+    }
+
+    void SetTarget(particles::Code targetCode) { event_->targetCode = targetCode; }
+  };
+
+} // namespace corsika::history
diff --git a/Stack/History/HStackView.hpp b/Stack/History/HStackView.hpp
deleted file mode 100644
index c5a7e1048..000000000
--- a/Stack/History/HStackView.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
- *
- * This software is distributed under the terms of the GNU General Public
- * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
- * the license.
- */
-
-#pragma once
-
-#include <corsika/stack/history/Event.hpp>
-
-#include <memory>
-
-namespace corsika::history {
-
-  template <typename TStackView>
-  class HStackView : public TStackView {
-    std::shared_ptr<Event<typename TStackView::StackIteratorValue>> event_;
-
-  public:
-    template <typename... Args>
-    EventBuilder(Args&&... args)
-        : TStackView{std::forward<Args>(args)}
-        , event_{std::make_shared<Event>()} {}
-
-    template <typename... Args>
-    void AddSecondary(Args&&... args) {
-      auto const s = TStackView::AddSecondary(
-          std::forward<Args>(args), event_); // what if event is not last argument?
-      event_->secondaries.emplace_back(s.GetEnergy(), s.GetMomentum(), s.GetParticleID());
-    }
-
-    void SetTarget(corsika::particles::ParticleCode targetCode) {
-      event_->targetCode = targetCode;
-    }
-  };
-
-} // namespace corsika::history
diff --git a/Stack/History/HistoryStackExtension.h b/Stack/History/HistoryStackExtension.h
index d12632d9e..58de264c1 100644
--- a/Stack/History/HistoryStackExtension.h
+++ b/Stack/History/HistoryStackExtension.h
@@ -49,7 +49,6 @@ namespace corsika::history {
   private:
     std::vector<std::shared_ptr<TEvent>> event_;
   };
-  
 
   /**
    * @class HistoryDataInterface
@@ -69,17 +68,16 @@ namespace corsika::history {
     using T::GetIndex;
 
   public:
- 
     // create a new particle from scratch
-    void SetParticleData() { } // nullptr, already by design 
+    void SetParticleData() {} // nullptr, already by design
 
     // create a new particle as secondary of a parent
-    void SetParticleData(HistoryDataInterface& parent) {
-      SetEvent(std::make_shared<TEvent>(parent.GetEvent()));
-      GetEvent().getParent().addSecondary(GetEvent());
+    void SetParticleData(HistoryDataInterface& parent) { SetParticleData(); }
+
+    void SetEvent(const std::shared_ptr<TEvent>& v) {
+      GetStackData().SetEvent(GetIndex(), v);
     }
 
-    void SetEvent(const std::shared_ptr<TEvent>& v) { GetStackData().SetEvent(GetIndex(), v); }
     std::shared_ptr<TEvent> GetEvent() const {
       return GetStackData().GetEvent(GetIndex());
     }
diff --git a/Stack/History/SecondaryParticle.hpp b/Stack/History/SecondaryParticle.hpp
index 319eeaa24..f1a2831d8 100644
--- a/Stack/History/SecondaryParticle.hpp
+++ b/Stack/History/SecondaryParticle.hpp
@@ -29,7 +29,9 @@ namespace corsika::history {
     // - polarization?
 
   public:
-    SecondaryParticle(units::si::HEPEnergyType energy, geometry::Vector<units::si::hepmomentum_d> momentum, particles::Code pid)
+    SecondaryParticle(units::si::HEPEnergyType energy,
+                      geometry::Vector<units::si::hepmomentum_d> momentum,
+                      particles::Code pid)
         : energy_{energy}
         , momentum_{momentum}
         , pid_{pid} {}
diff --git a/Stack/History/testHistory.cc b/Stack/History/testHistory.cc
index 468ca6415..ebc201ebe 100644
--- a/Stack/History/testHistory.cc
+++ b/Stack/History/testHistory.cc
@@ -7,63 +7,55 @@
  */
 
 #include <corsika/history/HistoryStackExtension.h>
-#include <corsika/stack/dummy/DummyStack.h>
 #include <corsika/stack/CombinedStack.h>
-
-using namespace corsika;
-using namespace corsika::stack;
+#include <corsika/stack/dummy/DummyStack.h>
+#include <corsika/history/Event.hpp>
+#include <corsika/history/HSecondaryView.hpp>
 
 #include <catch2/catch.hpp>
 
 #include <iostream>
-using namespace std;
-
-// this is our dummy environment, it only knows its trivial BaseNodeType
-class DummyEvent {
-public:
-  DummyEvent() {}
-  DummyEvent(const std::shared_ptr<DummyEvent>& parent) {
-    parent_ = parent;
-    //parent.addSecondary();
-  }
 
-  std::shared_ptr<DummyEvent> getParent() { return parent_; }
-  void addSecondary(const std::shared_ptr<DummyEvent>& particle) { secondaries_.push_back(particle); }
-
-  int multiplicity() const { return secondaries_.size(); }
-  
-private:
-  std::shared_ptr<DummyEvent> parent_;
-  std::vector<std::shared_ptr<DummyEvent>> secondaries_;
-};
+using namespace corsika;
+using namespace corsika::stack;
 
 // the GeometryNode stack needs to know the type of geometry-nodes from the DummyEnv:
 template <typename TStackIter>
-using DummyHistoryDataInterface = typename history::MakeHistoryDataInterface<TStackIter, DummyEvent>::type;
-
+using DummyHistoryDataInterface =
+    typename history::MakeHistoryDataInterface<TStackIter, history::Event>::type;
 
 // combine dummy stack with geometry information for tracking
 template <typename TStackIter>
-using StackWithHistoryInterface = corsika::stack::CombinedParticleInterface<
-  dummy::DummyStack::PIType,
-  DummyHistoryDataInterface, TStackIter>;
+using StackWithHistoryInterface =
+    corsika::stack::CombinedParticleInterface<dummy::DummyStack::PIType,
+                                              DummyHistoryDataInterface, TStackIter>;
 
-using TestStack = corsika::stack::CombinedStack<
-  typename stack::dummy::DummyStack::StackImpl,
-  history::HistoryData<DummyEvent>,
-  StackWithHistoryInterface>;
+using TestStack =
+    corsika::stack::CombinedStack<typename stack::dummy::DummyStack::StackImpl,
+                                  history::HistoryData<history::Event>,
+                                  StackWithHistoryInterface>;
 
+using EvtPtr = std::shared_ptr<history::Event>;
 
 TEST_CASE("HistoryStackExtension", "[stack]") {
 
   const dummy::NoData noData;
-  
+  TestStack s;
+
+  auto p = s.AddParticle(std::tuple<dummy::NoData>{noData});
+
+  SECTION("add lone particle") {
+    CHECK(s.GetSize() == 1);
+
+    EvtPtr evt = p.GetEvent();
+    CHECK(evt == nullptr);
+  }
+
   SECTION("write event") {
+    history::HSecondaryView hview{p};
 
-    TestStack s;
-    s.AddParticle(std::tuple<dummy::NoData>{noData});
-    REQUIRE(s.GetSize() == 1);
+    hview.AddSecondary(std::tuple<dummy::NoData>{noData});
   }
 
-  //REQUIRE(pout.GetPID() == particles::Code::Electron);
+  // REQUIRE(pout.GetPID() == particles::Code::Electron);
 }
-- 
GitLab