<commit_before>﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Assertions;
using Zenject;

namespace Alensia.Core.Physics
{
    public class CollisionBasedGroundDetector : GroundDetector, IInitializable
    {
        public override GroundDetectionSettings Settings
        {
            get { return _settings; }
        }

        public override Collider Target
        {
            get { return CollisionDetector.Target; }
        }

        public ICollisionDetector CollisionDetector { get; set; }

        private readonly GroundDetectionSettings _settings;

        public CollisionBasedGroundDetector(
            ICollisionDetector detector,
            GroundHitEvent groundHit,
            GroundLeaveEvent groundLeft) : this(
            new GroundDetectionSettings(), detector, groundHit, groundLeft)
        {
        }

        [Inject]
        public CollisionBasedGroundDetector(
            GroundDetectionSettings settings,
            ICollisionDetector detector,
            GroundHitEvent groundHit,
            GroundLeaveEvent groundLeft) : base(groundHit, groundLeft)
        {
            Assert.IsNotNull(settings, "settings != null");
            Assert.IsNotNull(detector, "detector != null");

            _settings = settings;
            CollisionDetector = detector;
        }

        public virtual void Initialize()
        {
            CollisionDetector.CollisionEntered.Listen(OnCollisionEnter);
            CollisionDetector.CollisionExited.Listen(OnCollisionExit);
        }

        public override void Dispose()
        {
            base.Dispose();

            CollisionDetector.CollisionEntered.Unlisten(OnCollisionEnter);
            CollisionDetector.CollisionExited.Unlisten(OnCollisionExit);
        }

        private void OnCollisionEnter(Collision collision)
        {
            var ground = FindGroundContacts(collision.contacts).FirstOrDefault();

            OnDetectGround(ground);
        }

        private void OnCollisionExit(Collision collision)
        {
            if (FindGroundContacts(collision.contacts).Exists(c => c == Ground))
            {
                OnDetectGround(null);
            }
        }

        protected virtual List<Collider> FindGroundContacts(IEnumerable<ContactPoint> contacts)
        {
            var center = Target.bounds.center.y;
            var extent = Target.bounds.extents.y;

            var bottom = center - extent;
            var groundContacts = from c in contacts
                where
                c.point.y <= bottom + Settings.Tolerance && IsGround(c.otherCollider)
                select c.otherCollider;

            return groundContacts.ToList();
        }<commit_msg>Allow overriding collision event callbacks<commit_after>﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Assertions;
using Zenject;

namespace Alensia.Core.Physics
{
    public class CollisionBasedGroundDetector : GroundDetector, IInitializable
    {
        public override GroundDetectionSettings Settings
        {
            get { return _settings; }
        }

        public override Collider Target
        {
            get { return CollisionDetector.Target; }
        }

        public ICollisionDetector CollisionDetector { get; set; }

        private readonly GroundDetectionSettings _settings;

        public CollisionBasedGroundDetector(
            ICollisionDetector detector,
            GroundHitEvent groundHit,
            GroundLeaveEvent groundLeft) : this(
            new GroundDetectionSettings(), detector, groundHit, groundLeft)
        {
        }

        [Inject]
        public CollisionBasedGroundDetector(
            GroundDetectionSettings settings,
            ICollisionDetector detector,
            GroundHitEvent groundHit,
            GroundLeaveEvent groundLeft) : base(groundHit, groundLeft)
        {
            Assert.IsNotNull(settings, "settings != null");
            Assert.IsNotNull(detector, "detector != null");

            _settings = settings;
            CollisionDetector = detector;
        }

        public virtual void Initialize()
        {
            CollisionDetector.CollisionEntered.Listen(OnCollisionEnter);
            CollisionDetector.CollisionExited.Listen(OnCollisionExit);
        }

        public override void Dispose()
        {
            base.Dispose();

            CollisionDetector.CollisionEntered.Unlisten(OnCollisionEnter);
            CollisionDetector.CollisionExited.Unlisten(OnCollisionExit);
        }

        protected virtual void OnCollisionEnter(Collision collision)
        {
            var ground = FindGroundContacts(collision.contacts).FirstOrDefault();

            OnDetectGround(ground);
        }

        protected virtual void OnCollisionExit(Collision collision)
        {
            if (FindGroundContacts(collision.contacts).Exists(c => c == Ground))
            {
                OnDetectGround(null);
            }
        }

        protected virtual List<Collider> FindGroundContacts(IEnumerable<ContactPoint> contacts)
        {
            var center = Target.bounds.center.y;
            var extent = Target.bounds.extents.y;

            var bottom = center - extent;
            var groundContacts = from c in contacts
                where
                c.point.y <= bottom + Settings.Tolerance && IsGround(c.otherCollider)
                select c.otherCollider;

            return groundContacts.ToList();
        }
{'fraction_non_alphanumeric': 0.06914027149321267, 'fraction_numerical': 0.0, 'mean_word_length': 2.0819854991634132, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '254627', 'n_tokens_mistral': 1384, 'n_tokens_neox': 1354, 'n_words': 280}